尝试在模拟服务上验证来自抽象 class 的方法调用,但我得到了一个 npe

Trying to verify a method call from abstract class on a mocked service but I get a npe

我在一个测试方法上坚持了几个小时。

我试图重现类似的情况。我有一个服务使用这样的实用方法扩展抽象服务:

public class MyService extends MyAbstractService {
    @Autowired
    private UserRepository userRepository;

    public void whatever(MyDTO myDTO) {
        User user = this.userRepository.findByName(myDTO.userId);
        hello(user.name);
    }
}

abstract class MyAbstractService {
    protected void hello(String userName) {
        System.out.printf("Hello %s", userName);
    }
}

我的测试class:

@Test
void whenIcallWhaterver() {
    MyService myService = Mockito.mock(MyService.class, InvocationOnMock::callRealMethod);

    myService.whatever(myDTO);
    verify(myService, only()).hello(anyString());
}

我的目标只是验证当我进入任何方法时,抽象服务的方法是否也被调用。我得到一个空指针异常,因为存储库不是在模拟中初始化(我假设的正常行为),但我想 learn/understand 如何测试它。

我该如何解决这个问题?

感谢您的帮助

您收到 NullPointerException,因为您没有将 UserRepository 对象设置为 MyService。

请注意,您的测试未加载任何 spring 上下文,因此 @Autowired 注释未生效。

所以为了让你的测试工作:

  • 通过构造函数或setter
  • 向您的服务添加模拟 UserRepository
  • 或将 spring 上下文加载到您的测试中并添加模拟 UserRepository。

例如,您可以执行以下操作:

@SpringBootTest(classes = MyTestConfig.class)
class MyTest {

  @MockBean
  private UserRepository userRepository;

  @SpyBean
  private MyService myService;

  @Test
  void whenIcallWhaterver() {

    // Mocks the response of the userRepository
    final User user = new User();
    user.setName("my-name");
    Mockito.when(this.userRepository.findByName(Mockito.anyString()))
            .thenReturn(user);

    final MyDTO myDTO = new MyDTO();
    myDTO.setUserId("myid");
    this.myService.whatever(myDTO);

    verify(this.myService).hello("my-name");
}

  @Configuration
  static class MyTestConfig {

    @Bean
    public MyService myService() {
        return new MyService();
    }
  }
}