【问题标题】:How to properly test internal method of class in java如何在java中正确测试类的内部方法
【发布时间】:2015-01-14 12:14:59
【问题描述】:

如何测试以下代码?

class1 {

    public InjectedClass injectedClass; 

    method1(){
        returnValue = injectedClass.someMethod; 
        //another logic
    }

    method2(){
        resultValue = method1();
    }

}

我的应用程序是用 Java 开发的。我使用 JUnit 和 Mockito。

为了测试method1(),我可以为InjectedClass 创建一个模拟,为someMethod() 创建一个模拟逻辑。 但是如何正确地测试一种方法呢?我需要为method1() 创建一个模拟吗?

更新: 让我演示一个真实的例子。

public class Application { 

@Inject 
DAOFacade facade;

//method1 
 public ReturnDTO getDTO(LiveServiceRequestParam requestParam) throws AffiliateIdentityException {
        ReturnDTO returnDTO  = new ReturnDTO();

        CoreProductRepository repo = recognizeProduct(ProdCodeTypeEnum.MPN, null, vendorBound);
        if(repo!=null){
           //logic to fill some fileds in returnDTO  
        }

        return returnDTO  ;
    }

//метод2 
 CoreProductRepository recognizeProduct(ProdCodeTypeEnum paramType, String prodCode, List<Integer> vendors) {
        CoreProductRepository coreProductRepository = null;
        switch (paramType) {
            case MPN:
                coreProductRepository = facade.findByAlternativeMPN(prodCode, vendors);
                break;
            case EAN:
                coreProductRepository = facade.findByEan(prodCode, vendors);
                break;
            case DESCRIPTION:
                coreProductRepository = facade.findByName(prodCode, vendors);
                break;
        }
        return coreProductRepository;
    }
}

所以,为了测试识别产品,我模拟了 DAOfacade。但我也想测试使用 identifyProduct 方法的 getDTO 方法。

【问题讨论】:

标签: java unit-testing testing junit mockito


【解决方案1】:

您应该将测试工作重点放在公共方法的返回值上,而不是内部实现上。

专注于内部实现会导致测试更难维护,因为不影响返回值的基本重构可能需要更改您的测试。

有时避免测试内部实现是不可能的,因为有些方法什么都不返回,你需要“断言”一些东西。在这种情况下,您似乎在某个时候返回了一些东西,我会专注于测试它。

【讨论】:

    【解决方案2】:

    您不需要模拟您的 recognizeProduct 方法。只要 DAOfacade 被模拟,行为是已知且确定的,因此 getDTO 和 recognizeProduct 的结果都可以验证。

    也可以说,你甚至不需要专门测试recognizeProduct,因为它不是公开的,所以没有强制执行的合同。只要getDTO 的行为正在被测试和验证,就用户而言,您的API 正在工作。实施的细节并不重要。

    在某种程度上,专门测试recognizeProduct 会适得其反,它会损害代码的可维护性和可靠性而不是帮助它,因为它使任何重构或重组更难实现,即使它不会影响外部可见任何方式的行为。

    【讨论】:

      【解决方案3】:

      如果方法如示例中所示定义,则它们是包私有的。因此,如果您在同一个包中创建测试(尽管通常在测试目录中),您将能够访问这些方法并对其进行测试。

      也就是说,如果您可以重构或重写该类以使其更易于测试,那么这可能是一个好主意。如果您确实必须测试内部方法的结果,而不能只测试公共方法。

      【讨论】:

        【解决方案4】:

        在我看来,您对 test 这个词有一个(可悲的是常见的)误解;它确实不是意味着“从测试用例执行”。

        测试意味着提供一系列输入,并断言相应的输出是正确的。 99% 的时间意味着检查返回码或对象状态,有时您必须使用模拟来正确测试纯输出接口。

        如果您对公共方法执行此操作,并且私有方法完全符合所需标准,那么工作就完成了。如果私有方法中有未发现的代码,则使用它来识别并添加丢失的测试用例,或者将其删除。

        如果您觉得通过删除无法访问的私有代码、将其公开或将其移至另一个类会丢失一些有用的东西。

        【讨论】:

        • 您能否进一步澄清一下。如果我将recognizeProduct 设为public 并且getDTO 使用它怎么办?在这种情况下method1的逻辑依赖于method2
        猜你喜欢
        • 1970-01-01
        • 2011-03-22
        • 2021-11-11
        • 2012-01-05
        • 2011-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多