模拟一个 void 方法
Mock a void method
//原方法:
@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 方法 并且它 不能 用 [ 存根=47=]价值!
Voids 通常用 Throwables 存根:
doThrow(异常).when(模拟).someVoidMethod();
如果您不确定为什么会出现上述错误,请继续阅读。
由于语法的性质,可能会出现上述问题,因为:
1. 您尝试存根的方法是 overloaded。确保您正在调用正确的重载版本。
2. 在你的测试中的某个地方,你正在存根 final 方法。抱歉,Mockito 没有 verify/stub final 方法。
3. 使用 when(spy.foo()).then() 语法对间谍进行存根。存根间谍更安全 -
- 使用 doReturn|Throw() 系列方法。更多关于 Mockito.spy() 方法的 javadocs。
4. 不支持在非 public 父级 类 上声明的模拟方法。
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);
}
}
}
It is a mock @InjectMocks ShellGeodeticService shellGeodeticService;
shellGeodeticService
不是模拟。 @InjectMocks
用于被测class,注入mocks
。
这意味着您不能使用
Mockito.when(shellGeodeticService.convertCRS(convertCrsVo))
.thenReturn(TestDataFactory.getCRSConversionResult());
在您的测试中,只有 mocks
(或 spys
) 可以在 Mockito.when
.
中使用
Actually im trying to run test case for shellGeodeticService.convertCRS() and since it calls isResponseValid method internally , i have to mock that also right?
不,那是不正确的。如果 validator
是一个 mock,默认情况下每个方法调用都不会执行任何操作。所以,除非你想抛出异常,否则你不需要定义任何东西。
由于您的问题缺少一些细节,我假设您的测试的完整版本可能与此类似:
@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)
returns false
默认
validator.isResponseValid( ... )
默认什么都不做
由于您没有添加方法 getCrsVoByCode
、getPerfByCode
和 generateLogMessage
请注意,如果与模拟对象有任何进一步的交互,您将需要添加它们。
(例如:对 geoCalService.search
的调用在您的测试代码中不可见,因此我从上面显示的测试中删除了行为定义)
//原方法:
@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 方法 并且它 不能 用 [ 存根=47=]价值! Voids 通常用 Throwables 存根: doThrow(异常).when(模拟).someVoidMethod();
如果您不确定为什么会出现上述错误,请继续阅读。 由于语法的性质,可能会出现上述问题,因为: 1. 您尝试存根的方法是 overloaded。确保您正在调用正确的重载版本。 2. 在你的测试中的某个地方,你正在存根 final 方法。抱歉,Mockito 没有 verify/stub final 方法。 3. 使用 when(spy.foo()).then() 语法对间谍进行存根。存根间谍更安全 - - 使用 doReturn|Throw() 系列方法。更多关于 Mockito.spy() 方法的 javadocs。 4. 不支持在非 public 父级 类 上声明的模拟方法。
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);
}
}
}
It is a mock @InjectMocks ShellGeodeticService shellGeodeticService;
shellGeodeticService
不是模拟。 @InjectMocks
用于被测class,注入mocks
。
这意味着您不能使用
Mockito.when(shellGeodeticService.convertCRS(convertCrsVo))
.thenReturn(TestDataFactory.getCRSConversionResult());
在您的测试中,只有 mocks
(或 spys
) 可以在 Mockito.when
.
Actually im trying to run test case for shellGeodeticService.convertCRS() and since it calls isResponseValid method internally , i have to mock that also right?
不,那是不正确的。如果 validator
是一个 mock,默认情况下每个方法调用都不会执行任何操作。所以,除非你想抛出异常,否则你不需要定义任何东西。
由于您的问题缺少一些细节,我假设您的测试的完整版本可能与此类似:
@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)
returnsfalse
默认validator.isResponseValid( ... )
默认什么都不做
由于您没有添加方法 getCrsVoByCode
、getPerfByCode
和 generateLogMessage
请注意,如果与模拟对象有任何进一步的交互,您将需要添加它们。
(例如:对 geoCalService.search
的调用在您的测试代码中不可见,因此我从上面显示的测试中删除了行为定义)