I am working on a Spring Java-based project. For testing purposes I have implemented a H2 in-memory DB, which has been filled with data via an xml doc. I whish to test a method which updates database records via an incoming datagram. First of all, this method check if there are any relevant data in the datagram arrived which are found in the database(here is a repository call), then calls for another external service with the given ids, which provides the actual data which needs to be placed into the DB instead of the already saved ones. So, there is a repository call first, then a second call for an external service. When I wish to test this function, I am using following annotations:
@RunWith(SpringRunner.class)
@SpringBootTest
@DatabaseSetup("classpath:datasets/FileWhichContainsDbRecords.xml")
Then I mock the external service with:
@MockBean
private ServiceName myService;
And call the Spring repository with:
@Autowired
private RepositoryName repositoryName;
And have the following test code:
@Test
@Transactional
public void testCase() {
GivenDg dg = Factory.createDg("id1", Collections.singletonList(Factory.createAnotherObject("id2", OPERATION_TYPE_MODIFY, Collections.singletonList("channel"))));
MyObject myObjectSavedInDB = repositoryName.findByProvidedIds("id1", "id2").get();
when(serviceName.getData(anyString(), anyString(), anyString(), any())).thenReturn(
Factory.createActualData(false, false, false, "HUF", Collections.singletonList("channels")));
myService.updateFunction(dg);
Optional<MyObject> optResult = repositoryName.findByProvidedIds("id1", "id2");
assertTrue(optResult.isPresent());
assertNotSame(optResult.get().isA(), myObjectSavedInDB.isA());
}
So, I which to mock the ServiceName service, and I have provided the response which I wish to have when this function is called but I keep getting NullPointer exception due to ServiceName is null. It does not even get mocked.
Is it not possible to test repository and mock a service in the same time? What am I doing wrong?
I would really appreciate any help!
Thank you!
java.lang.NullPointerException
at ---------)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Ok, I found what was missing... Originally, I had the following annotations on my Test class:
@RunWith(SpringRunner.class)
@SpringBootTest()
@DatabaseSetup("classpath:datasets/FileWhichContainsDbRecords.xml.xml")
@ContextConfiguration(classes = {TestRepositoryConfig.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class})
@DirtiesContext()
@Transactional
I had to add MockitoTestExecutionListener.class to the list of TestExecutionListeners....