使用存储库时服务出现 NullPointerException

NullPointerException from service when use repository

我对单元测试有疑问。我正在编写一个测试来检查服务是否正确保存数据(即不重复) 有一个服务 class 有几个字段,我们对 TypeRepository 字段感兴趣。在保存它的方法中调用并使用查找方法...在这种情况下,当我 运行 测试时,我得到 NullPointerException。我不知道在这种情况下有什么帮助。我将不胜感激

服务

@Service
@Slf4j
public class Service {
    ... 
    ...
    final RiskRepo riskRepo;
    ...
    ...
    private Limit validate(Limit newLimit) {
   
        RiskType.Value typeValue
                = riskRepo.findDistinctLimitTypeValueByLimitType(newLimitType);
                      //  ^--- exception
        
        switch (typeValue) { <-- warning can be null  
            case CONTY: {
                ...
                break;
            }

    ...
}

回购

public interface Repo extends JpaRepository<Limit, Integer> {


    @Query("SELECT DISTINCT r.Value from Type r WHERE r.limit=?1")
    RiskType.Value findDistinctValueByLimit(String limitType);
}

测试



 @Test
    public void test_validate() {
        Limit newLimit = Limit.builder()
                .riskType(...)
                ......build();

        limitService.create(newLimit);
        List<Limit>  limits = limitRepository.findAllByRiskTypeAndEntityAndLimitTypeAndUnitAndActive(
                newLimit.getRiskType(), newLimit.getEntity(), newLimit.getLimitType(),newLimit.getUnit(),newLimit.getActive());
        Assert.assertEquals(1, limits.size());
    }

您可以编写更多测试代码 class,因为它可能是测试配置问题或这些代码片段中没有的问题。但首先,确保你在你的服务上注入存储库,它看起来不像,所以用@Autowired 注释存储库属性或创建一个构造函数并在他内部启动存储库实例。另外一个可能出问题的是你的service方法是private的,需要是public,否则只有class服务才能访问到

关于测试,一般我做这类测试的时候,可以mock或者集成。

模拟测试:

您必须在服务测试 class 上方使用 @RunWith(MockitoJunitRunner.class) 等注释。然后注入服务并模拟您使用@Mock(repo)和@InjectMocks(服务)使用的存储库。

@RunWith(MockitoJUnitRunner.class)
public class YourTestClass {

@InjectMocks
private LimitService service;

@Mock
private LimitRepository repository;

@Test
public void test_validate(){
  
  when(this.repository...).thenReturn(...);

  this.service.doSomething();

  verify(this.repository).doSomething(...);
  verifyNoMoreInteractions(this.repository);
}

集成测试:

这里你要做的和repository test差不多,不同的是你需要调用SERVICE来调用repository方法。您需要像存储库测试一样将 class 配置为 运行 上下文。

@RunWith(SpringRunner.class)
@SpringBootTest
public class EmployeeRestControllerIntegrationTest {

    @Autowired
    private LimitService service;

    // write test cases here (such as your own, asserting the result of the service method return)
}

所以这些将是这两种类型的服务测试的解决方案,现在如果您需要测试存储库,我建议查看 Spring 引导存储库测试。

通过使用@Before 方法初始化存储库并将测试数据写入数据库,我能够解决问题

@Before
    public void setup() {
  Type type = new Type(
               data..);
        TypeRepository.save(type);

}