Reputation:
I have the following class:
@Service
public class SomeClass extends BaseClass {
private final SomeService someService;
public SomeClass(SomeService someService) {
this.someService = someService;
}
public List<String> methodToTest(SomeDataClass data) {
if (!checkData(data)) { // checkData is defined in BaseClass and does lots of unimportant stuff
throw BadDataException();
}
return someService.getData();
}
}
I now want to create testcases for SomeClass using Mockito.
Using Mockito, I've managed testcase 1 with:
@Test(expected = BadDataException.class)
public void methodToTest_checkDataCalled() {
SomeClass mock = mock(SomeClass.class);
when(mock.methodToTest(any()).thenCallRealMethod();
when(mock.checkData(any()).thenReturn(false);
mock.methodToTest(new SomeData());
verify(mock).checkData(any());
}
However, I have problems creating testcase #2. I can either create SomeClass manually with SomeClass someClass = new SomeClass(mockSomeService)
, but then I need to create mock data for the extensive checkData() request, which I don't actually want to test in this testcase since it's already covered by a different test and which requires a lot of unnecessary mocking, or I can mock SomeClass like in testcase #1, but then someService is always null, no matter what I try.
I've tried variations of @InjectMocks, @Mock and such, but I've failed to create a workable solution.
Things I've tried:
@Mock
private SomeService someService;
@Before
public void setUp() {
someService = mock(SomeService.class);
when(someService.getData()).thenReturn(Collections.singletonList("Mock"));
}
@Test
public void methodToTest_someServiceCalled1() {
SomeClass mock = mock(SomeClass.class);
when(mock.methodToTest(any()).thenCallRealMethod();
when(mock.checkData(any()).thenReturn(true);
List<String> result = mock.methodToTest(new SomeData()); // NullPointerException at someService.getData() call
verify(someService).getData();
assertEquals("Mock", result.get(0));
}
@Test
public void methodToTest_someServiceCalled2() {
SomeClass someClass = new SomeClass(someService);
List<String> result = someClass.methodToTest(new SomeData()); // Fails at checkData() call
verify(someService).getData();
assertEquals("Mock", result.get(0));
}
How can I have a call a mock for someService while still mocking the call to the parent classes checkData()? Is it possible without refactoring SomeClass?
Upvotes: 0
Views: 114
Reputation: 4259
If you create a mock of a class there won't be any dependencies in it. Instead use a spy on a real instance.
Here is a working example.
@Mock
private SomeService someService;
@InjectMocks
private SomeClass classUnderTest;
@Before
public void setUp() {
Mockito.when(someService.getData()).thenReturn(Collections.singletonList("Mock"));
}
@Test
public void methodToTest_someServiceCalled1() {
SomeClass spy = Mockito.spy(classUnderTest);
Mockito.when(spy.checkData(Mockito.any())).thenReturn(true);
List<String> result = spy.methodToTest(new SomeData());
Mockito.verify(someService).getData();
assertEquals("Mock", result.get(0));
}
I am not sure about you're 2nd test, afaik I would call the original checkData
method. As you mentioned that is something you want to avoid, the solution should be similiar to the 1st test.
Upvotes: 1