简体   繁体   English

如何调用另一种方法的单元测试方法?

[英]How to unit test method which invokes another method?

How to test method which invokes another method? 如何测试调用另一种方法的方法? In my example I would like to know how to test initComponentsTypeA which invokes create method. 在我的示例中,我想知道如何测试调用create方法的initComponentsTypeA

public MyClass{

private List<TypeA> componentsTypeA;

public void initComponents(Config c){   
    componentsTypeA = initComponentsTypeA(c);
    //...
}

private List<TypeA> initComponentsTypeA(Config c){
    //...
    List<MyObject> someList = c.getSomeList();
    List<TypeA> localList = new ArrayList<>();
    for(MyObject mo : someList){
        localList.add(create(mo));
    }
    return localList;
}

private TypeA create(MyObject myObject){
    // ...
}
}

I know that one solution is to refactor code in this way (show below). 我知道一种解决方案是以这种方式重构代码(如下所示)。 But is it necessary? 但这有必要吗? Is it the only solution? 这是唯一的解决方案吗?

public MyClass{

private List<TypeA> componentsTypeA;

public void initComponents(Config c){   
     List<MyObject> myObjectList = initComponentsTypeA(c);
     componentsTypeA = create(myObjectList)
    //...
}

private List<MyObject> initComponentsTypeA(Config c){
    //...
    List<MyObject> someList = c.getSomeList();
    return someList;
}

private List<TypeA> create(List<MyObject> myObjectList){
    // ...
}
}

In the second, refactored example the names of the methods are should be also changed, accordingly to their meaning. 在第二个重构示例中,方法的名称也应根据其含义进行更改。

You can use mockito and either create a mock that return real methods, then override the behaviour for the method you want to mock, or use spy, which creates a mock that wraps a real instance of your object. 您可以使用mockito并创建一个返回实际方法的模拟,然后覆盖您想要模拟的方法的行为,或者使用spy,它会创建一个包装对象的真实实例的模拟。

Here's a tutorial on mockito spy . 这是关于mockito间谍的教程。

Edit : 编辑

Since the method to be mocked is private, and as @fge mentioned, you would need mocking library that exposes private method. 由于要模拟的方法是私有的,并且正如@fge所提到的,您需要模拟库来公开私有方法。 And powermock , does just that. powermock ,做到这一点。

Given that initComponentsTypeA is a private method, you wouldn't unit test it directly. 鉴于initComponentsTypeA是私有方法,您不会直接对其进行单元测试。 You only ever want to unit test your public methods which then exercise your private members. 您只想对您的公共方法进行单元测试,然后运用您的私有成员。 You can confirm the effect of your private methods by looking at the side effects created by the calls to your private methods. 您可以通过查看调用私有方法所产生的副作用来确认私有方法的效果。

So in your case, you would test initComponents . 因此,在您的情况下,您将测试initComponents It is likely that in order to see what is going on within initComponents , you would need to pass in a mock Config object so you could verify that it is being used correctly and to control what it returns when getSomeList is called. 为了查看initComponents发生的事情,您可能需要传入一个模拟Config对象,以便验证它是否正确使用并控制调用getSomeList时它返回的getSomeList You would be able to confirm the effect of initComponentsTypeA and create by looking at the effect your call to initComponents had to other properties of the MyClass . 您可以通过查看对initComponents的调用对MyClass其他属性的影响来确认initComponentsTypeAcreate的效果。

If you don't have a way to see the changes to MyClass , you would need to consider refactoring your class to make that possible. 如果您无法查看对MyClass的更改,则需要考虑重构您的类以使其成为可能。 You need to think of your tests as testing MyClass from the persective of another class that is going to use MyClass . 你需要考虑你的测试,测试的MyClass从将要使用另一个类的persective MyClass If that class can't see or benefit from the effect of calling initComponents then it isn't much use to anyone. 如果该类无法看到或受益于调用initComponents的效果,那么它对任何人都没有多大用处。

Hopefully that is not too vague of an answer...let me know if you'd like me to clarify anything I've said above. 希望答案不要太模糊......如果你想让我澄清一下我上面所说的话,请告诉我。

You need to choose. 你需要选择。 Either you delegate all the private stuff to other classes, the methods are now public and your problems go away. 要么将所有私有内容委托给其他类,这些方法现在都是公开的,您的问题就会消失。

Or you are saying all that private stuff is private and as you don't test implementation. 或者你说所有私有东西都是私有的,因为你没有测试实现。 Any test on initComponents would have to be an indirect one. 对initComponents的任何测试都必须是间接测试。

If it's private from a unit testing point of view you could get rid of, or rename or otherwise twiddle with MyClass's implementation and hopefully have no impact on it's behaviour. 如果从单元测试的角度来看它是私有的,你可以摆脱,重命名或以其他方式扭曲MyClass的实现,并希望对它的行为没有影响。

It's a black box, or it's not... 这是一个黑盒子,或者它不是......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM