I have, for example, this class:
public class A {
private List<String> list;
public A(B b){
list = b.getList();
}
public List<String> someMethod(){
return list;
}
}
I want to unit test someMethod
without invoking constructor. I use reflection to set list
.
The problem is that I don't want to create B
class object and I cannot mock it since it will cause NPE.
So my question is:
How to test someMethod
without calling constructor of A
? Is there any way to mock class A and doesn't lose posibility to call methods?
Creating constructor with zero arguments is not a solution.
Note: I don't want to change any part of A class. I'm asking if it is possible to perform this test without adding or changing anything in A class.
You can test class A without calling it's constructor by Mockito. Not sure if I really understand your requirement but the following codes work for me.
import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ATest {
@Test
public void test() {
A a = mock(A.class);
when(a.someMethod()).thenCallRealMethod();
List<String> listInA = new ArrayList<String>();
ReflectionTestUtils.setField(a, "list", listInA);
assertThat(a.someMethod(), is(listInA));
}
}
You should mock out the collaborators to your class -- that means that you can create an instance of the class being tested, and pass in mocks, configured to 'do the right thing' when it's methods are called.
In your example, you want to create a mock B, and use it like this:
@RunWith(MockitoJUnitRunner.class)
class myTest {
@Mock private B b;
public void someMethod() {
doReturn(new ArrayList<String>()).when(b).getList();
A a = new A(b);
assertEquals("result", a.someMethod().get(0));
}
}
I don't want to create B class object
Add a constructor or factory method which doesn't require a B.
public A(B b){
this(b.getList());
}
/* package local */ A(List<String> list){
this.list = list;
}
By making the constructor package local it can be accessed by unit tests in the same package.
How to test someMethod without calling constructor of A?
You can use
A a = theUnsafe.allocateInstance(A.class);
but this is not recommended unless you have no other option e.g. deserialization.