簡體   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. 代碼如下:

我的服務:

 @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 因為我認為代碼的 rest 就足夠了。

據我所見,garageRepository 被實例化為模擬,因此 save 方法根本不知道要返回什么,並默認返回 null 。 如果調用save()方法,您必須告訴 Mockito 返回什么。 這可以通過Mockito.when(...).thenReturn(...)來實現。

您的測試應該測試服務,但您不會調用服務的單個方法!

另一方面,查詢存儲庫以獲取已保存的 object 是沒有意義的,因為 object 實際上沒有保存(同樣,存儲庫是一個模擬,您想測試服務,因此您要確保保存存儲庫的方法被正確調用)。 相反,您應該驗證 save() 方法是否像

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

...或者如果由於現有 object 具有相同的 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);
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM