如何测试以下代码?
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。但我也想要测试使用识别产品方法的getDTO方法。
你不需要模拟你的recognizeProduct
方法。只要模拟DAOfacade
,行为是已知的和确定的,因此可以验证getDTO
和recognizeProduct
的结果。
也可以说,你甚至不需要专门测试recognizeProduct
,因为它不是公开的,所以,没有合同可以执行。只要getDTO
的行为正在测试和验证,您的 API 就用户而言是有效的。实现的细节并不重要。
在某种程度上,测试recognizeProduct
会适得其反,它会损害代码的可维护性和可靠性,而不是帮助它,因为它使任何重构或重组更难实现,即使它不会以任何方式影响外部可见的行为。
如果按示例中所示定义方法,则它们是包私有的。因此,如果在同一包中创建测试(尽管通常在测试目录中),您将能够访问这些方法并对其进行测试。
也就是说,如果您可以重构或重写类以使其更容易测试,那么这可能是一个好主意。如果确实必须测试内部方法的结果,而不能只测试公共方法。
您应该将测试工作集中在公共方法返回值上,而不是不放在内部实现上。
专注于内部实现会导致测试更难维护,因为不影响返回值的基本重构可能需要更改测试。
有时无法避免测试内部实现,因为某些方法不返回任何内容,并且您需要"断言"某些内容。在这种情况下,您似乎在某个时候返回了一些东西,我会专注于测试它。
在我看来,你对测试这个词有一个(可悲的常见)误解; 它并不意味着"从测试用例执行"。
测试意味着提供一系列输入,并断言相应的输出是正确的。 99% 的时间这意味着检查返回代码或对象状态,有时您必须使用 mock 来正确测试纯输出接口。
如果您为公共方法执行此操作,并且私有方法完全涵盖到所需的标准,则工作完成。如果私有方法中有未覆盖的代码,请使用它来识别和添加缺少的测试用例,或者将其删除。
如果您觉得删除无法访问的私有代码会丢失一些有用的东西,请将其公开或将其移至另一个类。