JPARepository 保存方法返回 null?

时间:2021-07-18 13:10:33

标签: java junit spring-data-jpa mockito

我想为服务编写测试,但看起来 JPARepository.save 方法返回 null。 这是我来自 ServiceTest

的代码
@ExtendWith(MockitoExtension.class)

class PatientServiceTest {
@Mock
private PatientRepository patientRepository;
@Spy
private PatientMapper mapper = new PatientMapper();
@InjectMocks
private PatientService serviceUnderTests;

@Test
void whenCreatePatientByService_thenPatientRepositoryIsNotEmpty() {
    PatientModel patientModel = new PatientModel(134, "Pawel", "Nowak", 
    "pawel@test.pl", "123456789");
    serviceUnderTests.create(patientModel);

    assertNotNull(patientRepository.findAll());
}

服务代码

public PatientModel create(PatientModel patientModel) {
    PatientEntity patientEntity = mapper.from(patientModel);

    PatientEntity savedPatient = repository.save(patientEntity);
    return mapper.from(savedPatient);
}

这是调试模式下的屏幕截图:

enter image description here

Repository 只是 JPARepository 的接口,而 mapper 只有两个方法,实体到模型和模型到实体。

IntelliJ 说:

java.lang.NullPointerException: Cannot invoke "com.nowakpawel.healthcenter.repository.entity.PatientEntity.getId()" because "entity" is null

    at com.nowakpawel.healthcenter.service.mapper.PatientMapper.from(PatientMapper.java:24)
    at com.nowakpawel.healthcenter.service.PatientService.create(PatientService.java:29)
    at com.nowakpawel.healthcenter.service.PatientServiceTest.whenCreatePatientByService_thenPatientRepositoryIsNotEmpty(PatientServiceTest.java:44)

为什么当我想在Service中将Entity映射到Model时,Java将null放入from方法中,而PatientEntity em> 不为空?

3 个答案:

答案 0 :(得分:1)

PatientModel 作为参数传递给方法,并转换为PatientEntitypatientEntity 对象。由于它是一个单元测试并且 PatientRepository 已经被模拟,所以当某些东西被模拟时,你需要返回模拟的值。
所以应该为语句返回值

PatientEntity savedPatient = repository.save(patientEntity);

你可以这样写测试用例

void whenCreatePatientByService_thenPatientRepositoryIsNotEmpty() {
    PatientModel patientModel = new PatientModel(134, "Pawel", "Nowak", 
    "pawel@test.pl", "123456789");
    PatientEntity patientEntity = new PatientEntity();
    patientEntity.setXxxx("Nowak"); // Other values as per getter and setters

    doReturn(patientEntity).when(patientRepository).save(Matchers.any());
    
    PatientModel response = serviceUnderTests.create(patientModel);        
    
    assertNotNull(response);
    asserEquals("Nowak", response.getXxxxx()); //Getter method name here    
}

答案 1 :(得分:0)

谢谢大家回答我的问题。我错过了 Mockito 的那部分 ;) 但我还是有问题。这是我现在的代码:

@Test
    void whenCreatePatientByService_thenPatientRepositoryIsNotEmpty() {
        PatientModel patientModel = new PatientModel(14, "Pawel", "Nowak", "pawel@test.pl",
                "123456789");
    
    PatientEntity entity = mapper.from(patientModel);
    when(patientRepository.save(entity)).thenReturn(entity);
    serviceUnderTests.create(patientModel);
    assertNotNull(patientRepository.findAll());
}

并得到一个错误:

org.mockito.exceptions.misusing.PotentialStubbingProblem: 
Strict stubbing argument mismatch. Please check:
 - this invocation of 'save' method:
    patientRepository.save(
    PatientEntity [id=14, firstName='Pawel', lastName='Nowak', emailAddress='pawel@test.pl', phoneNumber='123456789']
);
-> at com.nowakpawel.healthcenter.service.PatientService.create(PatientService.java:28)
 - has following stubbing(s) with different arguments:
    1. patientRepository.save(
    PatientEntity [id=14, firstName='Pawel', lastName='Nowak', emailAddress='pawel@test.pl', phoneNumber='123456789']
);
      -> at com.nowakpawel.healthcenter.service.PatientServiceTest.whenCreatePatientByService_thenPatientRepositoryIsNotEmpty(PatientServiceTest.java:48)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API
    Please use 'will().given()' or 'doReturn().when()' API for stubbing.
  - stubbed method is intentionally invoked with different arguments by code under test
    Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.

据我所知 - 问题是

<块引用>

被测试的代码故意使用不同的参数调用存根方法

我说得对吗?为什么这是一个错误,而我将实体传递给 repository 保存方法?

这是我的整个项目,以防万一 -> https://github.com/nowakpawel/health-center

答案 2 :(得分:0)

好的,我找到了解决方案。刚刚将 equalshashCode 方法添加到 patientEntity

请关闭此线程,因为它已解决。

相关问题