jeudi 26 février 2015

Best practice - Setting a field without setters in a unit test

Let's say you have the following class you would like to test:



public class SomeService {
public String someMethod(ClassToTest objectToTest) {
return objectToTest.getSomeProperty();
}
}


The ClassToTest looks like this:



public class ClassToTest {
private String someProperty;

public getSomeProperty() {
return this.someProperty;
}
}


The assertion you would like to do can be the following:



String result = someService.someMethod(objectToTest);

assertThat(result).isEqualTo("someValue");


How can you make this test work?


1) Add a setter for 'someProperty' in the ClassToTest class. I don't think this a good solution because you don't change production code to make your tests work.


2) Use ReflectionUtils to set the value of this field. Test would look like this:



public class TestClass {
private SomeService someService;

@Test
public void testSomeProperty() {
ClassToTest objectToTest = new ClassToTest();
ReflectionTestUtils.setField(objectToTest, "someProperty", "someValue");

String result = someService.someMethod(objectToTest);

assertThat(result).isEqualTo("someValue");
}
}


3) You create an inner class in your test class that extends the ClassToTest class and adds the setter for this field. However, for this to work you will also need to change the ClassToTest class because the field should become 'protected' instead of 'private'. Test class might look like this:



public class TestClass {
private SomeService someService;

@Test
public void testSomeProperty() {
ObjectToTestWithSetters objectToTest = new ObjectToTestWithSetters();
objectToTest.setSomeProperty("someValue");

String result = someService.someMethod(objectToTest);

assertThat(result).isEqualTo("someValue");
}


public class ClassToTestWithSetters extends ClassToTest {
public setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
}
}


4) You use Mockito to mock ClassToTest. Seems fine if you only need to mock only one property in the class, but what if you need to mock like 10 properties are so. The test might look like this:



public class TestClass {
private SomeService someService;

@Test
public void testSomeProperty() {
ClassToTest objectToTest = mock(ClassToTest.class);
when(objectToTest.getSomeProperty()).thenReturn("someValue");

String result = someService.someMethod(objectToTest);

assertThat(result).isEqualTo("someValue");
}
}





Aucun commentaire:

Enregistrer un commentaire