1

This is a springmvc project based on gradle, I'm unit testing it using TestNG. When I mock a service layer class and stub its methods, "when (). ThenReturn ()" keeps reporting NullPointerException, I tried Many solutions on this site are not suitable for my situation.

controller:

package app.dnatask.controller;

import ...

@Slf4j
@RestController
@RequestMapping(value = "/API/scanresultconfigure")

public class ScanResultConfigureController extends BaseController {
    @Autowired
    private ScanResultConfigureService scanResultConfigureService;

    @RequestMapping(value = "/queryScanResultList/{taskId}/{externalname}", method = RequestMethod.POST)
    public IBaseResult queryscanResultList(final HttpServletRequest request, @PathVariable final String taskId, @PathVariable final String externalname, @RequestBody Map map) throws Exception {
        return runController(new IControllRunner() {
            public void run(IOutResult or, CheckResult cr) throws Exception {
                List<ScanResultTitleConfigurePO> list = scanResultConfigureService.findtitleConfigure(taskId, externalname, map);
                ......
            }
        }
    }
}

service:

package app.dnatask.service;

import ...

@Slf4j
@Service
public class ScanResultConfigureService {
    @Autowired
    private Demo1 demo1;
    @Autowired
    private Demo2 demo2;
    @Autowired
    private Demo3 demo3;

    public List<ScanResultTitleConfigurePO> findtitleConfigure(String taskId, String externalname, Map m) {
        //Query database
        List<ScanResultTitleConfigurePO> list = scanResultTitleConfigureRepository.findByTaskId(taskId, externalname);
        ......
        retuen list;
    }
}

unit test:

package app.dnatask.controller;

import ...

@WebAppConfiguration
@ContextConfiguration(classes = {ScanResultConfigureController.class})
@ComponentScan(
        excludeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {
                        ComponentScan.class, Configuration.class, ImportResource.class
                })
        },
        useDefaultFilters = false,
        lazyInit = true
)
@EnableWebMvc
public class ScanResultConfigureControllerTest extends AbstractTestNGSpringContextTests {
    @MockBean(answer = Answers.RETURNS_DEEP_STUBS)
    private ScanResultConfigureService scanResultConfigureService;

    @Autowired
    private WebApplicationContext webApplicationContext;
    private MockMvc mockMvc;

    @BeforeMethod
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).dispatchOptions(true).build();
        Demo1 demo1 = mock(Demo1.class,Answers.RETURNS_DEEP_STUBS);
        Demo2 demo2 = mock(Demo2.class,Answers.RETURNS_DEEP_STUBS);
        Demo3 demo3 = mock(Demo3.class,Answers.RETURNS_DEEP_STUBS);
    }

     @Test
    public void testQueryscanResultList() throws Exception {
        Map<String, String> testMap = new HashMap<>();
        testMap.put("key1", "value1");
        testMap.put("key2", "value2");
        String requestJson = JSONObject.toJSONString(testMap);
        List testList = new ArrayList();
        testList.add("test1");
        testList.add("test2");

        when(scanResultConfigureService.findtitleConfigure(anyString(), anyString(), anyMap())).thenReturn(testList);

        MvcResult mvcResult = mockMvc.perform(
                post("/API/scanresultconfigure/queryScanResultList/{taskId}/{externalname}", "123", "abc")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(requestJson)
        )
                .andExpect(status().isOk())
                .andDo(print())
                .andReturn();
    }
}

Exception message:

java.lang.NullPointerException
    at app.dnatask.controller.ScanResultConfigureControllerTest.testQueryscanResultList(ScanResultConfigureControllerTest.java:109)
    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.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133)
    at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:239)
    at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:180)
    at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:251)
    at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:580)
    at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:172)
    at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
    at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:804)
    at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:145)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.testng.TestRunner.privateRun(TestRunner.java:770)
    at org.testng.TestRunner.run(TestRunner.java:591)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:402)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:396)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:355)
    at org.testng.SuiteRunner.run(SuiteRunner.java:304)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1180)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1102)
    at org.testng.TestNG.runSuites(TestNG.java:1032)
    at org.testng.TestNG.run(TestNG.java:1000)
    at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.runTests(TestNGTestClassProcessor.java:139)
    at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.stop(TestNGTestClassProcessor.java:89)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy1.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:123)
    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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.lang.Thread.run(Thread.java:748)

This problem has bothered me for many days ... I really need your help ..

2 Answers2

0

The reason for NullpointerException could be that scanResultConfigureService.findtitleConfigure(anyString(), anyString(), anyMap()) is returning null or any intermediate method inside findtitleConfigure because it has not been stubbed before use.

You can create mocks for all intermediate return values and stub them before use. For example

FindTitleConfigure findTitleConfigure = mock(FindTitleConfigure.class);
Vishwa Ratna
  • 5,567
  • 5
  • 33
  • 55
  • According to your reminder, I thought it was because of generics. Because findtitleConfigure returned ```List ```; and ```when (). ThenReturn``` returned ```List ```. But when I removed the generics, it still reported ```NullPointerException```. – keshuan_jeme Dec 23 '19 at 02:22
  • You need to mock `findtitleConfigure` to return a list then use it. – Vishwa Ratna Dec 23 '19 at 02:25
  • I have tried the solution you mentioned above, but my findtitleConfigure does not have an intermediate return value.This method directly returns a List. – keshuan_jeme Dec 23 '19 at 02:44
  • And in spring projects, I can only use @MockBean to mock service classes. – keshuan_jeme Dec 23 '19 at 02:46
  • Oh, I think I found out what went wrong. Do you mean intermediate return refers to the database lookup method in service? After I mock the ```scanResultTitleConfigureRepository```, the unit test passed. I don’t even need to stub the ```findtitleConfigure``` method on service . – keshuan_jeme Dec 23 '19 at 02:57
0

Adding an annotation above the class of the unit test will solve the problem:

@TestExecutionListeners (listeners = MockitoTestExecutionListener.class)