23

When unit testing functions of a class that has private functions that require online functionality. How would one go about testing it?

For example:

public class Foo
{
    public int methodA()
    {
         int val = goOnlineToGetVal();

         return val;
    }

    private int goOnlineToGetVal()
    {
        CloudService c = new CloudService();
        int oval = c.getValueFromService();
        return oval;
    }
}

If I were to test function: 'methodA()' it would attempt to use 'goOnlineToGetVal()' which would in turn try to go online however, if this test was done without functionality. How would I go about 100% Class coverage without going online?

2 Answers2

77

new CloudService()

And there's your problem.

Modern OO design recommends that this sort of dependency be passed in rather than constructed directly. This can be passed into the function itself, or to the class at construction time. It could also be grabbed or aggregated by an Inversion of Control container if that sort of complexity is warranted.

At that point, it becomes fairly trivial to pass in a mock/fake service to provide you with your "online" data during testing. Better yet, it allows your software to be sufficiently flexible, so that you can quickly adapt should some (governmental?) client comes along and doesn't want to use the cloud for their values. Or you want to dump one cloud provider for another. Or...

Telastyn
  • 110,259
37

I would implement it like this:

public class Foo
{
    private ICloudService cloudService;

    public Foo(ICloudService s)
    {
       cloudService=s;
    }

    public int methodA()
    {
         int val = goOnlineToGetVal();

         return val;
    }

    private int goOnlineToGetVal()
    {
        int oval = cloudService.getValueFromService();
        return oval;
    }
}

The interface ICloudService can be either implemented with a mock for testing, or with the "real" cloudservice. When the instantiation new CloudService() is mandatory for every call of getValueFromService, or CloudServiceis from a 3rd party API which cannot be changed, implement a wrapper, deriving from ICloudService and making the appropriate calls.

Doc Brown
  • 218,378