Junit replace properties - java

I'd like to change from which .properties file class should get them.
My class is like this now:
public class MyClass {
private String str;
public MyClass() throws IOException {
loadProperties();
}
private void loadProperties() throws IOException {
Properties props = new Properties();
props.load(getClass().getClassLoader().getResourceAsStream("my.properties"));
str= props.getProperty("property");
}
And whyle testing i would like properties to be loaded from another file.
It's apache camel app, so i have this now:
public class ConverterTest {
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new MyClass(); //--> Here i must load from another file
}
#Test
// test
}
Can this be achieved?

Just pass property file name to MyClass constructor
public MyClass(String propsFile) throws IOException {
loadProperties(propsFile);
}

There is something you can do:
public class MyClass {
private String str;
private String path = "my.properties";
public MyClass() throws IOException {
loadProperties();
}
protected void loadProperties() throws IOException {
Properties props = new Properties();
props.load(getClass().getClassLoader().getResourceAsStream(path));
str= props.getProperty("property");
}
And then, add a test to the same package with the code:
myClass = new MyClass();
ReflectionTestUtils.setField(path, "otherpathto.properties");
myClass.loadProperties();
It involves a small change in the code, but it might not be a big deal... depending on your project.

Arguably the cleanest solution would be to refactor MyClass and remove dependency on Properties object and inject the values needed via the constructor instead. Your case proves that hidden and hardcoded dependencies complicate testing.
Responsibility for reading the properties file and injecting the value into MyClass could be pushed back to its caller:
public class MyClass {
private final String str;
public MyClass(String strValue) {
this.str = strValue;
}
// ...
}
public class ProductionCode {
public someMethod() {
Properties props = new Properties();
props.load(getClass().getClassLoader().getResourceAsStream("my.properties"));
String str = props.getProperty("property");
MyClass obj = new MyClass(str);
obj.foo();
}
}
public class ConverterTest {
#Test
public void test() {
String testStr = "str for testing";
MyClass testee = new MyClass(testStr);
testee.foo();
// assertions
}
}

Related

How do I mock the Property.load() method?

public class Foo {
public A getSomething() {
Properties file = loadProperties().getProperty(something);
}
public static Properties loadProperties() {
Properties properties = new Properties();
properties.load(Foo.class.getClassLoader().getResourceAsStream("id"));
}
return properties;
}
What I did is:
#InjectMocks
Foo foo = new Foo();
#Test
public void test() {
MockitoAnnotations.initMocks(this);
Properties properties = Mockito.mock(Properties.class);
Mockito.doNothing().when(properties).load(new FileInputStream("application.properties")
foo.getSomething();
}
It throws null pointer exception in properties.load method. Any help would be appreciated.
Thank you.

How to inject mocks into a class that has 1 constructor with parameters?

I have the following class (Condensed it to focus on issue instead of showing entire class):
#Component
public class ABCDEF {
private final Helper helper;
private final URI uri;
public ABCDEF(Helper helper, #Value("${endpoint.url}") URI uri) {
this.helper = helper;
this.uri = uri;
}
public void b(){
helper.toString();
}
}
For its test, I am looking to inject the mocks as follows but it is not working.
The helper comes up as null and I end up having to add a default constructor to be able to throw the URI exception.
Please advice a way around this to be able to properly inject the mocks. Thanks.
#RunWith(JUnitMockitoRunner.class)
public class ABCDEFTest {
#Mock
private Helper helper;
#InjectMocks
private ABCDEF abcdef = new ABCDEF(
helper,
new URI("test")
);
// adding just to be able to throw Exception
public ABCDEFTest() throws URISyntaxException {
}
#Test
public void b() {
abcdef.b();
}
}
Note: Using Mockito version 1.10.19. Will need to stick to this version.
This should work:
#RunWith(MockitoJUnitRunner.class)
public class ABCDEFTest {
#Mock
private Helper helper;
private ABCDEF abcdef;
#Before
public void setUp() throws URISyntaxException {
abcdef = new ABCDEF(
helper,
new URI("test")
);
}
#Test
public void b() {
abcdef.b();
}
}
Or, instead of using #RunWith, you can initialize mock inside setUp method:
public class ABCDEFTest {
private Helper helper;
private ABCDEF abcdef;
#Before
public void setUp() throws URISyntaxException {
helper = Mockito.mock(Helper.class);
abcdef = new ABCDEF(
helper,
new URI("test")
);
}
#Test
public void b() {
abcdef.b();
}
}

How to verify a method was called inside another method with Mockito

I'm fairly new to Mockito, and I've been looking for a way to verify that if I call the filter() method with the right string, that the foo method will get called once.
public class A
{
private final Config _config;
public A(Config config) { _config = config; }
public void filter(String str)
{
if(str.startsWith("a"))
{
if(str.contains("z"))
{
foo(config.getName());
}
}
}
private void foo(String bar)
{
(...)
}
}
Here is my current code:
#Test
public void testOne()
{
Config config = new Config(configFile);
A a = Mockito.spy(new A(config));
a.filter("abcz");
verify(a, times(1)).foo(someString);
}
Try to be more generic while such a test. If you don't need to specify what exactly argument should by passed then just use any():
import static org.mockito.ArgumentMatchers.any;
verify(a).foo(any(String.class));

java - reflection: How to Override private static abstract inner class method?

I have the following class:
class MyClass{
private static final int VERSION_VALUE = 8;
private static final String VERSION_KEY = "versionName";
public boolean myPublicMethod(String str) {
try {
return myPrivateMethod(str, VERSION_KEY, VERSION_VALUE,
new MyInnerClass() {
#Override
public InputStream loadResource(String name) {
//do something important
}
});
}
catch (Exception e) {
}
return false;
}
private boolean myPrivateMethod(String str, String key, int version,
ResourceLoader resourceLoader) throws Exception
{
//do something
}
private static abstract class MyInnerClass {
public abstract InputStream loadResource(String name);
}
}
I want to write unit test for myPrivateMethod for which I need to pass resourceLoader object and override it's loadResource method.
Here is my test method:
#Test
public void testMyPrivateMethod() throws Exception {
Class<?> cls = Class.forName("my.pack.MyClass$MyInnerClass");
Method method = cls.getDeclaredMethod("loadResource", String.class);
//create inner class instance and override method
Whitebox.invokeMethod(myClassObject, "testValue1", "testValue2", "name1", 10, innerClassObject);
}
Note, that I can't change code.
Well, you could use Javassist...
See this question. I haven't tried this, but you can call this method when you want the override:
public <T extends Object> T getOverride(Class<T> cls, MethodHandler handler) {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(cls);
factory.setFilter(
new MethodFilter() {
#Override
public boolean isHandled(Method method) {
return Modifier.isAbstract(method.getModifiers());
}
}
);
return (T) factory.create(new Class<?>[0], new Object[0], handler);
}
Well, the problem i see with your code is that you are calling myPublicMethod and you are giving fourth parameter as new MyInnerClass(). Now in your private method fourth parameter is given as ResourceLoader and from your code i see no relation between MyInnerClass and ResourceLoader. So you can try out following code. It might help.
Despite your warning that you cannot change the code i have changed it because i was trying to run your code.
class MyClass{
private static final int VERSION_VALUE = 8;
private static final String VERSION_KEY = "versionName";
public boolean myPublicMethod(String str) {
try {
return myPrivateMethod(str, VERSION_KEY, VERSION_VALUE,
new MyInnerClass() {
#Override
public InputStream loadResource(String name) {
return null;
//do something important
}
});
}
catch (Exception e) {
}
return false;
}
private boolean myPrivateMethod(String str, String key, int version,
MyInnerClass resourceLoader) throws Exception
{
return false;
//do something
}
private static abstract class MyInnerClass {
public abstract InputStream loadResource(String name);
}
}
Hope it helps.

call a java properties class

Need to create a class that i can load properties in and be able to call required properties from that class. such as propertiesClass.getname();
Here's my Class so far. I can't seem to initiate the property load.
So what i need is from another class in the project to just do (currently getting null)
String url = TestProperties.getBaseUrl();
*updated the class, here's what it looks like now.
public class TestProperties {
private static Properties testProperties;
private static String instanceUrl;
public TestProperties() throws Exception{
loadProperties();
getInstanceProperties();
instanceUrl = TestProperties.testProperties.getProperty("confluence.base.url","");
}
public static String getBaseUrl(){
return instanceUrl;
}
private void loadProperties() throws IOException {
InputStream testPropertiesInput = this.getClass().getClassLoader().getResourceAsStream("smoketest.properties");
TestProperties.testProperties = new Properties();
// if (null != testProperties) {
try{
TestProperties.testProperties.load(testPropertiesInput);
} finally {
IOUtils.closeQuietly(testPropertiesInput);
}
// }
}
}
my otherclass(){
String myurl = TestProperties.getBaseUrl();
}
The method
public void TestProperties() throws Exception{
was meant to be constructor but isn't one, so the class only gets a default no-arg constructor. Change that to:
public TestProperties() throws Exception{
i.e. remove the return type as constructors are distinguished from ordinary methods by not declaring a return type.
Please make sure you are able to rightly access your properties file smoketest.properties though InputStream testPropertiesInput.
EDIT:
There is no need to redefine the local variable in loadProperties and return it. It can be written very simply as:
private static void loadProperties() throws IOException {
InputStream testPropertiesInput = getClass().getClassLoader()
.getResourceAsStream("smoketest.properties");
Properties testProperties = new Properties();
try{
TestProperties.testProperties.load(testPropertiesInput);
} finally {
IOUtils.closeQuietly(testPropertiesInput);
}
TestProperties.testProperties = testProperties;
}
I think public void TestProperties() throws Exception{ is constructor of your class. If yes, please remove void from it as it making it as a method.
Finally you may want to use testProperties in your TestProperties() constructor as :
public TestProperties() throws Exception{
loadProperties();
getInstanceProperties();
instanceUrl = TestProperties.testProperties
.getProperty("confluence.base.url","");
}
Please Note: I don't think your class variables should be defined as static. Is there any reason of doing so?
EDIT: Here is the hopefully working sample code for you:
public class TestProperties {
private static Properties testProperties;
private static String instanceUrl;
public TestProperties(){
try{
loadProperties();
//getInstanceProperties();
instanceUrl = TestProperties.testProperties
.getProperty("confluence.base.url","");
}catch(IOException ioe){
ioe.printStackTrace();
}
}
static{
//Just to initialize the properties
new TestProperties();
}
private void loadProperties() throws IOException {
InputStream testPropertiesInput = getClass().getClassLoader()
.getResourceAsStream("smoketest.properties");
Properties testProperties = new Properties();
try{
testProperties.load(testPropertiesInput);
} finally {
IOUtils.closeQuietly(testPropertiesInput);
}
TestProperties.testProperties = testProperties;
}
public static String getBaseUrl(){
return instanceUrl;
}
public static String getPropertyValue(String key){
return TestProperties.testProperties.getProperty(key,"Not Found");
}
}
Now you can simply get your base URL any where as :
public static void main(String[] args) {
System.out.println(TestProperties.getBaseUrl());
System.out.println(TestProperties.getPropertyValue("confluence.base.url"));
System.out.println(TestProperties.getPropertyValue("test.property"));
}

Categories

Resources