Spring MongoDB的单元测试返回null



我正在尝试对基于MongoDB的Spring Boot应用程序进行单元测试,但遇到了java.lang.NullPointerException: Cannot invoke "blueprint.model.Garage.getCarModel()" because "savedGarage" is null错误。代码如下:

我的服务:

@Service
public class GarageService {
private final GarageRepository garageRepository;
@Autowired
public GarageService(GarageRepository garageRepository) {
this.garageRepository = garageRepository;
}
public void addToGarage(Garage garage) {
Optional<Garage> garageOptional = garageRepository.findByCarModel(garage.getCarModel());
if(garageOptional.isPresent()) {
throw new IllegalStateException("This Car model is already in our garage!");
}
garageRepository.save(garage);
}
public List<Garage> showOurGarage() {
return garageRepository.findAll();
}
public void deleteFromGarage(String id) {
boolean exists = garageRepository.existsById(id);
if(!exists) {
throw new IllegalStateException("A car with id " + id + " is not in our Garage.");
}
garageRepository.deleteById(id);
}
public void updateCar(String id, String carModel, Integer HP, Integer year, String designer) {
Garage garage = garageRepository.findById(id)
.orElseThrow(() -> new IllegalStateException(
"A car with the id " + id + " is not in our Garage."));
if(carModel != null && carModel.length() > 0 && !Objects.equals(garage.getCarModel(), carModel)) {
garage.setCarModel(carModel);
}
if(HP != null && !Objects.equals(garage.getHP(), HP)) {
garage.setHP(HP);
}
if(year != null && !Objects.equals(garage.getYear(), year)) {
garage.setYear(year);
}
if(designer != null && designer.length() > 0 && !Objects.equals(garage.getDesigner(), designer)) {
garage.setDesigner(designer);
}
garageRepository.save(garage);
}
}

我的存储库:

@org.springframework.stereotype.Repository
public interface GarageRepository extends MongoRepository<Garage, String> {
Optional<Garage> findByCarModel(String carModel);

这里有一个测试:

@DisplayName("Garage Service Test")
@DataMongoTest
class GarageServiceTest {
@Mock
private GarageRepository garageRepository;
private GarageService garageService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
garageService = new GarageService(garageRepository);
}
@Test
@DisplayName("Add Car To Garage Test")
void testAddToGarage() {
Garage testGarage = new Garage();
testGarage.setId("630ca281f12905d5f5249f08");
testGarage.setCarModel("Shelby Cobra");
testGarage.setHP(485);
testGarage.setYear(1965);
testGarage.setDesigner("Carroll Shelby");
Garage savedGarage = garageRepository.save(testGarage);
String testedGarage = savedGarage.getCarModel();
Optional<Garage> garages = garageRepository.findByCarModel("Shelby Cobra");
assertEquals(testedGarage, garages.toString());
}

我对单元测试和MongoDB非常熟悉,所以我不确定这个错误发生在哪里以及为什么发生。我跳过了添加Controller,因为我认为剩下的代码就足够了。

据我所见,garageRepository被实例化为mock,因此save方法根本不知道返回什么,默认情况下返回null。如果调用了save()方法,您必须告诉Mockito返回什么。这可以通过Mockito.when(...).thenReturn(...)来实现。

您的测试应该测试服务,但您不会调用服务的单个方法

另一方面,查询存储库中保存的对象是没有意义的,因为该对象实际上是而不是保存的(同样,存储库是一个mock,您需要测试服务,因此需要确保正确调用存储库的保存方法(。相反,您应该验证save((方法是否像一样被调用

Mockito.verify(garageRepository).save(testGarage);

或者由于具有相同id的现有对象而出现异常。尝试以下代码(未测试!(:

@DisplayName("Garage Service Test")
@DataMongoTest
class GarageServiceTest {
@Mock
private GarageRepository garageRepository;
private GarageService garageService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
//This would be the way to make the mock return sth., 
//but not really   needed
//Garage returnObject = new Garage();
//returnObject.setId("630ca281f12905d5f5249f08");
//returnObject.set...(...);
//Mockito.when(garageRepository.save(Mockito.ANY))
//   .thenReturn(returnObject);
garageService = new GarageService(garageRepository);
}
@Test
@DisplayName("Add Car To Garage Test")
//This is the 'positive test, object isn't persisted yet
void testAddToGarage() {
Garage testGarage = new Garage();
testGarage.setId("630ca281f12905d5f5249f08");
testGarage.setCarModel("Shelby Cobra");
testGarage.setHP(485);
testGarage.setYear(1965);
testGarage.setDesigner("Carroll Shelby");
Mockito.when(garageRepository
.findByCarModel(testGarage.getCarModel()))
.thenReturn(Optional.empty());
garageService.addToGarage(testGarage);
Mockito.verify(garageRepository).save(testGarage);
}
@Test
@DisplayName("Add Car To Garage Test")
//This is the 'negative' test, the repository indicates that the object
//is already persisted
@Expected(IllegalStateException.class)
void testAddToGarageAlreadyPersisted() {
Garage testGarage = new Garage();
testGarage.setId("630ca281f12905d5f5249f08");
testGarage.setCarModel("Shelby Cobra");
testGarage.setHP(485);
testGarage.setYear(1965);
testGarage.setDesigner("Carroll Shelby");
Mockito.when(garageRepository
.findByCarModel(testGarage.getCarModel()))
.thenReturn(Optional.of(testGarage));
garageService.addToGarage(testGarage);
Mockito.verify(garageRepository, Mockito.never()).save(testGarage);
}

}