-2

I am getting null pointer exception while testing. Here is the test class.

@SpringBootTest
public class RunSummaryServiceImplTest {

    @Spy   //Tried @Mock too
    private RunSummaryRepository runSummaryRepository;

    /** The file repository. */
    @Spy
    private FileRepository fileRepository;

    @InjectMocks
    RunSummaryServiceImpl runSummaryServiceImpl;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void TestprocessCustomerRunSummaries() {

        final RunSummaryServiceImpl runSummaryServiceImpl = new RunSummaryServiceImpl();
        final Collection<RunSummary> runs = new ArrayList<>();
        runs.add(new RunSummary("customer1", 1, Timestamp.valueOf("2023-05-30 10:00:00")));
        runs.add(new RunSummary("customer2", 2, Timestamp.valueOf("2023-05-30 11:00:00")));
        runs.add(new RunSummary("customer3", 3, Timestamp.valueOf("2023-05-30 12:00:00")));

        runSummaryServiceImpl.processCustomerRunSummaries(runs);  //NULL POINTER EXCEPTION HERE
    }
}

I tried using @Spy also instead of @Mock,also I tried changing @SpringBootTest with @ExtendWith still getting same issue.

Also I cant use when.thenReturn(),because the method processCustomerRunSummaries() is void.

Here is the ServiceImpl Class

    @Service
    public class RunSummaryServiceImpl implements RunSummaryService {

    /** LOGGER. */
    private static final Logger LOGGER = LogManager.getLogger(RunSummaryServiceImpl.class.getName());

    /** RunSummaryRepository reference. */
    @Autowired
    private RunSummaryRepository runSummaryRepository;

    /** The file repository. */
    @Autowired
    private FileRepository fileRepository;

    
    @Override
    public void processCustomerRunSummaries(final Collection<RunSummary> runs) {
        LOGGER.debug("Customer RunSummary list size : {}", runs.size());
        final long start = System.currentTimeMillis();
        for (final RunSummary run : runs) {
    // Get RunSummaryEntity for each group. Create/update RunSummaryEntity statics for    each group.
        processCustomerRunSummary(run);
        }
    LOGGER.info("All {} Customer Run Summaries processing finished in {} milliseconds.", runs.size(),
            System.currentTimeMillis() - start);
    }

    
    @Override
    public void processCustomerRunSummary(final RunSummary run) {
        LOGGER.debug("Processing Customer Run Summary : {}", run);
        final String customerId = run.getCustomerId();
        final Integer solutionNumber = run.getSolutionNumber();
        final Timestamp downloadDatetime = run.getDownloadDatetime();

        try {
    //check if RunSummary is present in RunSummaryEntity.if not,create a RunSummaryEntity.If present     then
            // append its statistics.
            final RunSummaryEntity runEntityDb = runSummaryRepository
     .findByCustomerIdAndSolutionNumberAndDownloadDatetime(customerId, solutionNumber,downloadDatetime);

            if (null == runEntityDb) {
            createCustomerRunSummary(run, customerId, solutionNumber, downloadDatetime);
            } else {
            // runEntityDb exist in DB so update it with latest Statistics
        updateCustomerRunSummary(run, customerId, solutionNumber, downloadDatetime, runEntityDb);
            }
        } catch (final DataAccessException daException) {
        // just catch and log DataAccessException so that next RunSummaries should be processed.
    LOGGER.error("DataAccessException while processing customer RunSummary: {} , error: {}", run,
                daException);
        }
    }

Also adding the stack trace below

  java.lang.NullPointerException
    at     com.oversighttech.ocr.service.impl.RunSummaryServiceImpl.processCustomerRunSummary(RunSummaryServiceImpl.java:74)
    at com.oversighttech.ocr.service.impl.RunSummaryServiceImpl.processCustomerRunSummaries(RunSummaryServiceImpl.java:52)
    at com.oversighttech.ocr.service.impl.RunSummaryServiceImplTest.TestprocessCustomerRunSummaries(RunSummaryServiceImplTest.java:53)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    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.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    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.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
shreyash
  • 1
  • 1
  • 1
    Does this answer your question? [Why are my mocked methods not called when executing a unit test?](https://stackoverflow.com/questions/74027324/why-are-my-mocked-methods-not-called-when-executing-a-unit-test) – `final RunSummaryServiceImpl runSummaryServiceImpl = new RunSummaryServiceImpl();` shadows your field with the same name. The instance with injected mocks is never used. Also, you need to chose Mockito-based tests or Spring-based tests. – knittl May 31 '23 at 20:07

2 Answers2

0

You're nullifying the Mock by creating a new instance of the service in your test.

Remove

final RunSummaryServiceImpl runSummaryServiceImpl = new RunSummaryServiceImpl();

Since your test class already has a member variable called runSummaryServiceImpl that has the mocks injected, your test should simply look like this:

@Test
public void TestprocessCustomerRunSummaries() {
    final Collection<RunSummary> runs = new ArrayList<>();
    runs.add(new RunSummary("customer1", 1, Timestamp.valueOf("2023-05-30 10:00:00")));
    runs.add(new RunSummary("customer2", 2, Timestamp.valueOf("2023-05-30 11:00:00")));
    runs.add(new RunSummary("customer3", 3, Timestamp.valueOf("2023-05-30 12:00:00")));

    // This is created as a mock at the class level
    runSummaryServiceImpl.processCustomerRunSummaries(runs);
}
lane.maxwell
  • 5,002
  • 1
  • 20
  • 30
  • Removed that still getting null pointer exception at runSummaryServiceImpl.processCustomerRunSummaries(runs); this line – shreyash May 31 '23 at 17:20
  • Ah, I just noticed that you're mixing SpringBootTest with Mocks. They don't work together too well. In looking at your test, you aren't actually using any of the mocking aspects, nor are you using your Spys. Remove any references to the Mock stuff (including your @Before method, replace the `@InjectMocks` annotation on your service to just Autowired. If you do want to use mocks with SpringBootTest, use @MockBean so it's part of the context. – lane.maxwell May 31 '23 at 19:05
0

Hy

I think you can use this example :

when(myMock.doSomething()).thenThrow(new MyException());

Or you can annotate your test with :

@Test(expected=MyException.class)
Samuel_
  • 177
  • 3
  • 16