简体   繁体   English

Spock-模拟的存储库方法save()给出NullPointerException

[英]Spock - mocked repository method save() giving NullPointerException

I'm using Spock to unit test a service in my app. 我正在使用Spock对应用程序中的服务进行单元测试。 Recently I encountered a weird behavior I don't really understand. 最近,我遇到了一个我不太了解的怪异行为。

Here is my unit test: 这是我的单元测试:

def setup() {
    parkingSessionRepository = Mock(ParkingSessionRepository.class)
    parkingSessionMapper = Stub(ParkingSessionMapper.class)

    parkingMeterService = new ParkingMeterService(parkingSessionRepository, parkingSessionMapper)
}

def "should start parking session for vehicle that doesn't have an active parking session"() {

    given:
    String testVehicleId = "AWC1342"
    long testParkingRateId = 1

    ParkingStartDTO testParkingStartDTO = ParkingStartDTO.builder()
            .vehicleId(testVehicleId)
            .parkingRateId(testParkingRateId)
            .build()

    ParkingSession testParkingSession = ParkingSession.builder()
    .vehicleId(testVehicleId)
    .parkingRate(ParkingRate.REGULAR)
    .build()

    parkingSessionMapper.fromParkingStartDTO(_) >> testParkingSession
    parkingSessionRepository.save(_ as ParkingSession) >> testParkingSession

    parkingSessionRepository.findByVehicleIdAndStopTimeIsNull(_ as String) >> Optional.empty()

    when:
    ParkingMeterResponseDTO parkingMeterResponseDTO = parkingMeterService.startParkingMeter(testParkingStartDTO)

    then:
    1 * parkingSessionRepository.save(_ as ParkingSession)

    parkingMeterResponseDTO.vehicleId == testVehicleId
    Assert.assertNotNull(parkingMeterResponseDTO.parkingSessionId)
    Assert.assertNotNull(parkingMeterResponseDTO.timestamp)
}

While code for tested service method is: 而经过测试的服务方法的代码是:

public ParkingMeterResponseDTO startParkingMeter(final ParkingStartDTO parkingStartDTO) {

    String vehicleId = parkingStartDTO.getVehicleId();

    if (isParkingSessionAlreadyActive(vehicleId)) {
        throw new ParkingSessionAlreadyActiveException();
    } else {

        ParkingSession parkingSession = parkingSessionMapper.fromParkingStartDTO(parkingStartDTO);
        parkingSession.setStartTime(Timestamp.from(Instant.now()));
        parkingSession = parkingSessionRepository.save(parkingSession);

        return ParkingMeterResponseDTO.builder()
                .vehicleId(parkingSession.getVehicleId())
                .parkingSessionId(parkingSession.getId())
                .timestamp(parkingSession.getStartTime())
                .build();
    }
}

Now, when I run unit test there is a result of NullPointerException coming from 'when' block (save() method returns null). 现在,当我运行单元测试时,来自“ when”块的结果是NullPointerException(save()方法返回null)。 However, when I remove save() method check from 'then' block - everything works smoothly, no nulls. 但是,当我从'then'块中删除save()方法检查时-一切运行顺利,没有null。

What could be a reason for such behaviour? 发生这种行为的原因可能是什么? I suspect some mocking issues with Repository, but I'm not sure what exactly happens under the hood and how to resolve the issue so the save() method check in 'then' block works as intended? 我怀疑存储库存在一些模拟问题,但是我不确定幕后到底发生了什么以及如何解决该问题,因此“ then”块中的save()方法按预期工作了吗?

Please check Spock documentation: http://spockframework.org/spock/docs/1.0/interaction_based_testing.html 请检查Spock文档: http : //spockframework.org/spock/docs/1.0/interaction_based_testing.html

Section: Combining Mocking and Stubbing 部分: 模拟和存根结合

Combining: 结合:

given:
...
parkingSessionRepository.save(_ as ParkingSession) >> testParkingSession
...
then:
1 * parkingSessionRepository.save(_ as ParkingSession)

Will not work. 不管用。 You have to use one expression: 您必须使用一个表达式:

1 * parkingSessionRepository.save(_ as ParkingSession) >> testParkingSession

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

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