首页 > 解决方案 > 试图在模拟服务上验证来自抽象类的方法调用,但我得到了一个 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);
    }
}

我的测试课:

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

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

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

我该怎么做才能解决这个问题?

谢谢你的帮助

标签: javajunitmockitojunit5springmockito

解决方案


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

请注意,您的测试没有加载任何弹簧上下文,因此注释 @Autowired 没有生效。

因此,为了让您的测试正常工作:

  • 通过构造函数或设置器将模拟 UserRepository 添加到您的服务
  • 或将弹簧上下文加载到您的测试中并添加模拟 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();
    }
  }
}

推荐阅读