简体   繁体   English

Spring MongoDB 的单元测试返回 null

[英]Unit test of Spring MongoDB returns null

I'm trying to Unit test my MongoDB-based Spring Boot application, and I'm getting a java.lang.NullPointerException: Cannot invoke "blueprint.model.Garage.getCarModel()" because "savedGarage" is null error. I'm trying to Unit test my MongoDB-based Spring Boot application, and I'm getting a java.lang.NullPointerException: Cannot invoke "blueprint.model.Garage.getCarModel()" because "savedGarage" is null error. The code is down below:代码如下:

My Service:我的服务:

 @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);
}
}

My Repository:我的仓库:

@org.springframework.stereotype.Repository
public interface GarageRepository extends MongoRepository<Garage, String> {

Optional<Garage> findByCarModel(String carModel);

And here's a test:这是一个测试:

@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());
}

I'm pretty much green with Unit testing and MongoDB, so I'm not sure where and why this error happens.我对单元测试和 MongoDB 非常满意,所以我不确定这个错误发生在哪里以及为什么会发生。 I've skipped adding the Controller because I think the rest of the code will be sufficient.我已经跳过添加 Controller 因为我认为代码的 rest 就足够了。

From what I see, garageRepository is instantiated as a mock, so the save method doesn't know at all what to return and returns null by default.据我所见,garageRepository 被实例化为模拟,因此 save 方法根本不知道要返回什么,并默认返回 null 。 You have to tell Mockito what to return if the save() method is called.如果调用save()方法,您必须告诉 Mockito 返回什么。 This can be achieved by Mockito.when(...).thenReturn(...) .这可以通过Mockito.when(...).thenReturn(...)来实现。

Your test should test the service, but you don't call a single method of the service!您的测试应该测试服务,但您不会调用服务的单个方法!

On the other hand, it doesn't make sense to query the repository for the saved object as the object is actually not saved (again, the repository is a mock, you want to test the service so you want to make sure that the save method of the repository is called correctly).另一方面,查询存储库以获取已保存的 object 是没有意义的,因为 object 实际上没有保存(同样,存储库是一个模拟,您想测试服务,因此您要确保保存存储库的方法被正确调用)。 Instead, you should verify that the save() method is called like相反,您应该验证 save() 方法是否像

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

...or if there is an exception due to an existing object with the same id. ...或者如果由于现有 object 具有相同的 id 而出现异常。 Try the following code (not tested:):尝试以下代码(未测试:):

@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);
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM