使用存储库时服务出现 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);
}
我对单元测试有疑问。我正在编写一个测试来检查服务是否正确保存数据(即不重复) 有一个服务 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);
}