Home > database >  NPE while running test in Spring application (JUnit 5, Mockito 3, Spring JPA repositories)
NPE while running test in Spring application (JUnit 5, Mockito 3, Spring JPA repositories)

Time:11-04

I'm running a basic Spring App with Mockito 3.1.0 and and Junit 5.5.2. I have a Service call that includes two Spring Data JPA repositories. These are passed into the constructor for DI (along with two others that are immaterial – I'm including them in case they could also, potentially, cause errors.) I see no issues with the service when the app runs.

When I run my test, I get a NPE for myService. Stepping through the stack trace, hasn't really shown me anything that relates to the error. I have also tried (following this Article: https://www.baeldung.com/mockito-junit-5-extension) updating my test class to look like this:

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class) // This dependency doesn't seem to exist
public class MyServiceTest {
    // ...

    @BeforeEach 
    // not the JUnit4 @Before annotation.
    // Interestingly, this gives me NPEs for the repositories, not the service.
    public void setup(){
        // ...
    }
}

to no avail. What I suspect is happening is that something about my setup isn't properly wired up – either as dependencies or syntax for DI.

How do I debug this? What am I missing? Thanks in advance!

Service:

import org.springframework.stereotype.Service;

@Service
public class MyService {
    private final Repository1 repository1;
    private final Repository2 repository2;
    private final Repository3 repository3;
    private final Repository4 repository4;

  public MyService(Repository1 repository1,
      Repository2 repository2,
      Repository3 repository3,
      Repository4 repository4) {
    this.repository1 = repository1;
    this.repository2 = repository2;
    this.repository3 = repository3;
    this.repository4 = repository4;
  }

    public Boolean computeValue(String someInput) {
        // does computations with repository1, repository2.
    }
}

Test:

import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {

    @Mock
    private Repository1 repository1;

    @Mock
    private Repository2 repository2;

    @Mock
    private Repository3 repository3;

    @Mock
    private Repository4 repository4;

    @InjectMocks
    private MyService myService;

    @Before
    public void setup {
        when(repository1.findAll()).thenReturn(new ArrayList<>());
        when(repository1.findAllByInput(anyString())).thenReturn(new ArrayList<>());
        // Yes; I'm aware that this could also be a call to
        // MockitoAnnotations.initMocks(this). I've tried it:
        // it doesn't work. Also, I've intentionally not taken this
        // approach due to reasons:
        //   - https://stackoverflow.com/questions/10806345/runwithmockitojunitrunner-class-vs-mockitoannotations-initmocksthis
    }

    @Test
  void callMyService() {
        assertTrue(myService.computeValue("123"));
    }
}

Sample Repository:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

// This is just an example, but this pattern is repeated against all
// repositories in the project.
@Repository
public interface Repository1 extends JpaRepository<Repository1, String> {
}

Edit:

  • I forgot to mention that I have other files in this project that are using exactly these annotations (@RunWith(MockitoJUnitRunner.class), @Mock, @InjectMocks, @Before) that are not failing.
  • I updated the files with the relevant imports, and added an example of RepositoryN.
  • I update the MyService class to better reflect the parameters.

CodePudding user response:

For anybody else who encounters this in the future, we were able to fix this problem by changing one of the imports from:

import org.junit.jupiter.api.Test;

to

import org.junit.Test;

CodePudding user response:

Seems like your object myService, is not instantiated. I would suggest not use @InjectMocks and directly create your object as your repositories are already instantiated. MyService myService = new MyService(..., ..., ...)

CodePudding user response:

I suppose you have to annotate your test class with @ExtendWith(SpringExtension.class) and not with MockitoExtension.class

More info here Junit 5 with Spring Boot: When to use @ExtendWith Spring or Mockito?

  • Related