模拟无效方法

时间:2019-10-24 20:10:37

标签: junit mockito junit4 junit5 powermockito

//原始方法:

@Autowired
    private ConversionServiceValidator validator; 

    public CRSConversionResult convertCRS(ConvertCrsVo convertCrsVo) throws Exception {

if (validator.isSameSourceAndTarget(convertCrsVo))
            throw new ValidationException(Constants.BADREQUEST);

        if (convertCrsVo.getPreferredTransforms() != null) {
            List<TransformVo> preferredTransformList = new ArrayList<>();
            for (TransformVo transformVo : convertCrsVo.getPreferredTransforms()) {
                preferredTransformList.add(getPerfByCode(transformVo));
            }
            convertCrsVo.setPreferredTransforms(preferredTransformList);
        }
        convertCrsVo.setSourceCRS(getCrsVoByCode(convertCrsVo.getSourceCRS()));
        convertCrsVo.setTargetCRS(getCrsVoByCode(convertCrsVo.getTargetCRS()));
        convertCrsVo = validator.replaceCoordinates(convertCrsVo);
        logger.info("ShellGeodeticService::convertCRS::Request to GeoCalService convertpoints::" + mapper.writeValueAsString(convertCrsVo));
        ConvertPointsResponse response = geoCalService.convertCRS(convertCrsVo);
        CRSConversionResult result = new CRSConversionResult();
        result.setCriteriaMessage(response.getCriteriaMessage());
        result.setResultPoints(response.getResultPoints());
        result.setTransformName(response.getTransformName());
        result.setTransformDescription(response.getTransformDescription());
        // added schema as per pbi 195298
        List<ConvertedTransformsResult> transformsResults = new ArrayList<>();
        if (response.getTransforms() != null || !response.getTransforms().isEmpty())
            response.getTransforms().stream().forEach(
                    t -> transformsResults.add(new ConvertedTransformsResult().getConvertedTransformsResult(t)));
        result.setTransforms(transformsResults);
        String logmessage=generateLogMessage(result,convertCrsVo);
        logger.info(logmessage);
        validator.isResponseValid(result);
        return result;
}

//上述方法的测试用例

@Test
    public void testconvertCRSJob() throws Exception{
        ConvertCrsVo convertCrsVo = TestDataFactory.getConvertCrsVo();
        CRSConversionResult crsConversionResult = TestDataFactory.getCRSConversionResult();
        ConversionServiceValidator conversionServiceValidatorMock = mock(ConversionServiceValidator.class);
Mockito.when(geoCalService.convertCRS(Mockito.any()))
        .thenReturn(TestDataFactory.getConvertPointsResponse(convertCrsVo));
Mockito.when(validator.replaceCoordinates(convertCrsVo))
        .thenReturn(TestDataFactory.getConvertCrsVo());
Mockito.when(geoCalService.search(Mockito.any(SearchFilter.class)))
        .thenReturn(TestDataFactory.getSearchResultResponseForCRS());
Mockito.when(shellGeodeticService.convertCRS(convertCrsVo))
        .thenReturn(TestDataFactory.getCRSConversionResult());  
shellGeodeticService.convertCRSJob();

        }

我得到的错误如下:

org.mockito.exceptions.misusing.CannotStubVoidMethodWithReturnValue: ' isResponseValid '是 void方法,并且不能加上返回值! 虚空通常与Throwables一起使用:     doThrow(exception).when(mock).someVoidMethod();


如果不确定为什么会遇到错误,请继续阅读。 由于上述语法的性质,可能由于以下原因而出现问题: 1.您尝试存根的方法是重载。确保您正在调用正确的重载版本。 2.在测试的某个地方,您正在存根最终方法。抱歉,Mockito不验证/存根最终方法。 3.使用when(spy.foo())。then()语法对间谍进行打桩。对间谍进行存根比较安全-    -使用doReturn | Throw()系列方法。有关Mockito.spy()方法的更多Javadocs。 4.不支持在非公共父类上声明的模拟方法。

at com.shell.geodetic.GeodeticConvertionApiAppTests.testconvertCRSJob(GeodeticConvertionApiAppTests.java:1783)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

有人可以帮助我如何对void方法“ isResponseValid”进行存根吗?我尝试了大约100种在SOF中看到的组合,但没有任何效果。感谢您的提前帮助。

*编辑

Class ConversionServiceValidator {

    public void isResponseValid(CRSConversionResult response) throws InvalidDataException {

            if (response.getResultPoints().isEmpty() || response.getResultPoints() == null) {
                throw new ValidationException("Request body has incorrect format");
            } else {
                for (Point point : response.getResultPoints()) {
                    if (point.getX().trim().equals("0") || point.getY().trim().equals("0")) {
                        throw new InvalidDataException(400, "Bad Request", "WARNING: Not all points could be converted",
                                response);
                    }
                }
}

1 个答案:

答案 0 :(得分:0)

  

这是一个模拟@InjectMocks ShellGeodeticService shellGeodeticService;

shellGeodeticService不是一个模拟。 @InjectMocks用于被注入mocks的被测类。

这意味着您不能使用

Mockito.when(shellGeodeticService.convertCRS(convertCrsVo)) 
       .thenReturn(TestDataFactory.getCRSConversionResult());

在测试中,因为mocks中只能使用spys(或Mockito.when)。


  

实际上,我正在尝试为shellGeodeticService.convertCRS()运行测试用例,并且由于它在内部调用了isResponseValid方法,因此我也必须对此进行模拟吗?

不,那是不正确的。如果validator是模拟的,则默认情况下,每个方法调用都不会执行任何操作。因此,除非要抛出异常,否则无需定义任何内容。


由于您的问题缺少一些细节,因此我认为您的测试的完整版本可能与此类似:

@InjectMocks
ShellGeodeticService shellGeodeticService;

@Mock
ConversionServiceValidator validator;

@Mock
... geoCalService; // some unknown class

@Test
public void testconvertCRSJob() throws Exception{

    ConvertCrsVo convertCrsVo = TestDataFactory.getConvertCrsVo();

    // Note sure whether this is correct by your logic as there is no `replacement` happening.
    Mockito.when(validator.replaceCoordinates(convertCrsVo)).thenReturn(convertCrsVo);

    Mockito.when(geoCalService.convertCRS(Mockito.any())).thenReturn(TestDataFactory.getConvertPointsResponse(convertCrsVo));

    CRSConversionResult result = shellGeodeticService.convertCRS();

    // do some assertions on the result
}

validator是一个模拟:

  • validator.isSameSourceAndTarget(convertCrsVo)返回false为默认
  • validator.isResponseValid( ... )默认不执行任何操作

由于您没有添加方法getCrsVoByCodegetPerfByCodegenerateLogMessage,因此请注意,如果与模拟对象有任何进一步的交互,则需要添加它们。 (例如:对geoCalService.search的调用在您的测试代码中不可见,因此我从上面显示的测试中删除了行为定义)