NPE while 运行 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)

我正在 运行使用 Mockito 3.1.0 和 Junit 5.5.2 构建一个基本的 Spring 应用程序。我有一个包含两个 Spring Data JPA 存储库的服务调用。这些被传递到 DI 的构造函数中(连同其他两个无关紧要的东西——我将它们包括在内,以防它们也可能导致错误。)当应用程序 运行s 时,我发现服务没有问题.

当我 运行 我的测试时,我得到了 myService 的 NPE。单步执行堆栈跟踪,并没有真正向我显示与错误相关的任何内容。我也尝试过(根据这篇文章:https://www.baeldung.com/mockito-junit-5-extension)将我的测试 class 更新为如下所示:

@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(){
        // ...
    }
}

无济于事。我怀疑正在发生的事情是关于我的设置的某些东西没有正确连接——无论是作为 DI 的依赖项还是语法。

我该如何调试它?我错过了什么?提前致谢!

服务:

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.
    }
}

测试:

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:
        //   - 
    }

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

示例存储库:

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> {
}

编辑:

您的对象 myService 似乎未实例化。我建议不要使用 @InjectMocks 并直接创建你的对象,因为你的存储库已经实例化了。 MyService myService = new MyService(..., ..., ...)

我想你必须用 @ExtendWith(SpringExtension.class) 而不是 MockitoExtension.class

来注释你的测试 class

这里有更多信息

对于以后遇到此问题的任何其他人,我们可以通过更改其中一个导入来解决此问题:

import org.junit.jupiter.api.Test;

import org.junit.Test;

编辑:

  • 这与不同版本的 JUnit 有关。关于为什么 .
  • 有一个很好的长篇解释