java - 在对特定方法进行 Junit 测试用例和模拟时,如何避免调用内部方法结构的级联

标签 java unit-testing junit mockito junit4

我正在使用 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/

相关文章:

php - 如何 mock 模拟内部方法

c# - 适用于 Windows 7 的 Microsoft Windows SDK 是否包含用于 MS 单元测试的库?

java - 使用 PowerMockito.whenNew() 不会被模拟并调用原始方法

java - 如何为构造函数制作测试用例

java - 在 Intents 中传递 FirebaseFirestore 引用

java - Maven 的新手在 Netbean 中创建 Maven 项目时出错

java - 使用 2 个不同的类打印偶数和奇数

Java:从 MySQL 检索记录时结果集为空

javascript - Karma 单元测试 : Module name "react" has not been loaded yet for context: _. 使用 require([])

java - 当软件已经传递给客户时,包是否应该包含单元测试/测试类? JAVA