Tiny Rick
Tiny Rick

Reputation: 276

Mocking a static method

Below is the method i want to test. I am using TestNG framework for unit testing.

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. I can provide some dummy cktNames and get the method to execute like below.

@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. It has to return something in order for my "method" to work. I searched the internet and found "easymock" as a solution. But i am unable to use "easyMock" to mock the static method (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.

Upvotes: 0

Views: 1252

Answers (2)

Aasmund Eldhuset
Aasmund Eldhuset

Reputation: 38000

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:

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.

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.

Upvotes: 1

BetaRide
BetaRide

Reputation: 16894

You need PowerMock to do mock static methods directly. See https://github.com/jayway/powermock/wiki/TestNG_usage

Upvotes: 4

Related Questions