我正在使用 Junit 为公共(public)方法创建一个测试用例。该方法正在调用同一类中的私有(private)方法,并且该私有(private)方法最终根据业务逻辑调用单独类中的其他方法的序列。
所有方法都返回 ConcurrentHashMap,我只想测试返回值的 assertNotNull
。
如何避免方法调用的级联?
如果我去模拟流程的所有方法,那么我的测试用例就会变得巨大。 我如何避免这些调用并仅对我的方法执行黑盒测试,即传递参数和预期返回。
我的方法是:
public ConcurrentHashMap<String, Object> checkValidation(Validation validationData,
ConcurrentHashMap<String, Object> srcHMData, Statement statement) {
Column[] columnArray = validationData.getColumnArray();
ConcurrentHashMap<String, Object> processedData = new ConcurrentHashMap<String, Object>();
ConcurrentHashMap<String, Object> validationData = null;
if (columnArray != null && columnArray.length > 0) {
for (int i = 0; i < columnArray.length; i++) {
validationData = new ConcurrentHashMap<String, Object>();
Column colVal = columnArray[i];
String validationName = colVal.getName();
validationData = processValidation(validationName, srcHMData, statement);
processedData.putAll(validationData);
}
}
return processedData;
}
它从此类调用的私有(private)方法是:
private ConcurrentHashMap<String, Object> processValidation(String validationName,
ConcurrentHashMap<String, Object> srcHMData, Statement statement) {
ConcurrentHashMap<String, Object> validationData = new ConcurrentHashMap<String, Object>();
try {
TransformationProcess transferObj = new TransformationProcess();
validationData = transferObj.checkTransformation(srcHMData, statement);
} catch (Exception e1) {
e1.printStackTrace();
}
return validationData;
}
我尝试过的测试方法如下:
TransformationProcess transMock = mock(TransformationProcess.class);
when(transMock.checkTransformationRule(Mockito.any(), eq(dummyDataMap), eq(mockStatement))).thenReturn(validationDataMap);
我想避免从私有(private)方法中的这一行调用内部方法 -
validationData = transferObj.checkTransformation(srcHMData, statement);
并且只想从这一行返回一个模拟ConcurrentHashMap,以便我可以测试assertNotNull
或其他一些。
但是当遇到这一行时,它正在调用整个业务流程并最终得到 NullPointer 异常。
最佳答案
您不能使用mockito来模拟new
的调用。这里有两个选择:第一个是使用 powermock
,它可以比mockito做更多的事情,但建议仅用于遗留代码,第二个是重构您的代码,以便您可以将 TransformationProcess
的依赖项注入(inject)到您的 Validator
中。
您可以直接将 TransformationProcess
注入(inject)到您的方法中:
public ConcurrentHashMap<String, Object> checkValidation(Validation validationData,
ConcurrentHashMap<String, Object> srcHMData, Statement statement, TransformationProcess transformationProcess)
这种方式看起来并不优雅,因为您必须将此依赖项传递给每个需要它的私有(private)方法。
或者可以通过构造函数注入(inject)依赖项:
Validator(TransformationProcess transformationProcess)
现在,您可以重用对象中已有的同一实例,而不是每次都创建新实例。如果您每次都需要 TransformationProcess
的新实例,则可以在构造函数中注入(inject)将提供新实例的 TransformationProcess
包装器:
Validator(TransformationProcessProvider transformationProcessProvider)
...
TransformationProcess transformationProcess = transformationProcessProvider.getTransformationProcess();
现在您可以创建 TransformationProcessProvider
的模拟并将其传递给正在测试的对象:
TransformationProcessProvider providerMock = mock(TransformationProcessProvider.class);
TransformationProcess transMock = mock(TransformationProcess.class);
when(providerMock.getTransformationProcess()).thenReturn(transMock);
when(transMock.checkTransformationRule(Mockito.any(), eq(dummyDataMap), eq(mockStatement))).thenReturn(validationDataMap);
Validator validatorUnderTest = new Validator(providerMock);
关于java - 在对特定方法进行 Junit 测试用例和模拟时,如何避免调用内部方法结构的级联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55534402/