简体   繁体   English

模拟静态方法

[英]Mocking a static method

Below is the method i want to test. 下面是我要测试的方法。 I am using TestNG framework for unit testing. 我正在使用TestNG框架进行单元测试。

class Random{

    List<String> namesOfLinks;

    public List<String> methodIwantToTest(List<String> cktNames) {
            Map<String, Graph> maps =   DataBaseReader.getGraphs(cktNames);
            for (Entry<String, Graph> entry : maps.entrySet()) {
                graphList.add(entry.getValue().getName());
            }
    }

    return namesOfLinks;
}

I am writing the test cases for the method "methodIwantToTest" in the above class. 我正在上面的类中编写方法“ methodIwantToTest”的测试用例。 I can provide some dummy cktNames and get the method to execute like below. 我可以提供一些虚拟的cktNames并让该方法执行如下。

@Test (dataProvider = "dp")
public void test_methodIwantToTest(List<String> cktNames, List<String> expectedLinkNames){
    Random rm = new Random();
    List<String> actual = rm.methodIwantToTest(cktNames);
    Assert.assertEquals(actual,expectedLinkNames);
} 

Now comes the problem. 现在出现了问题。 When the actual method is executing when i invoke it on the 'rm' reference, it has a static method call to another API. 当我在'rm'引用上调用实际方法时,它将对另一个API进行静态方法调用。 It has to return something in order for my "method" to work. 为了我的“方法”起作用,它必须返回一些东西。 I searched the internet and found "easymock" as a solution. 我在互联网上搜索并找到“ easymock”作为解决方案。 But i am unable to use "easyMock" to mock the static method (DataBaseReader.getGraphs()). 但是我无法使用“ easyMock”来模拟静态方法(DataBaseReader.getGraphs())。 I have to mock that method so that it returns a map of the defined type. 我必须模拟该方法,以便它返回已定义类型的映射。 Any suggestions would be great. 任何建议都很好。 Thanks !! 谢谢 !!

Other questions deal with how to test static methods. 其他问题涉及如何测试静态方法。 But mine is about mocking a static method while testing a instance method. 但是我的想法是在测试实例方法时模拟静态方法。

You need PowerMock to do mock static methods directly. 您需要PowerMock直接模拟静态方法。 See https://github.com/jayway/powermock/wiki/TestNG_usage 参见https://github.com/jayway/powermock/wiki/TestNG_usage

I would recommend using the Adapter pattern in combination with the Dependency Injection technique. 我建议将适配器模式与依赖注入技术结合使用。 Create an interface that contains all the methods you want to mock: 创建一个包含要模拟的所有方法的接口:

public interface IDatabase {
    Map<String, Graph> getGraphs(List<String> names);
}

Obviously, Database doesn't implement the interface you just invented (and the method is static anyway), but you can create an adapter class: 显然, Database并没有实现您刚发明的接口(该方法无论如何都是static的),但是您可以创建一个适配器类:

public class DataBaseReaderAdapter implements IDatabase {
    public Map<String, Graph> getGraphs(List<String> names) {
        return DataBaseReader.getGraphs(names);
    }
}

Take an instance of this class as a constructor parameter in the class you want to test: 将此类的实例作为您要测试的类中的构造函数参数:

public class Random {
    private readonly IDatabase _database;

    public Random(IDatabase database) {
        _database = database;
    }
}

and when you want to call the method: 以及何时要调用该方法:

Map<String, Graph> maps = _database.getGraphs(cktNames);

In your test, use any mocking framework to create a mock of IDatabase , and pass that mock to Random . 在测试中,使用任何模拟框架来创建IDatabase的模拟,然后将该模拟传递给Random

While this technique might seem pretty involved at first, it tends to lead to better designs in which the dependencies of a class are more visible and everything becomes easier to test. 尽管此技术乍看之下似乎很复杂,但它往往会导致更好的设计,在该设计中,类的依赖关系更加可见,并且所有内容都变得更易于测试。

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

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