开发者

Correct way to unit test private variables

I have the following method:

private string _google = @"http://www.google.com";

public ConnectionStatus CheckCommunicationLink()
{
    //Test if we can get to Google (A happy website that should always be there).
    Uri googleURI = new Uri(_google);
    if (!IsUrlReachable(googleURI, mGoogleTest开发者_StackOverflowString))
    {
        //The internet is not reachable.  No connection is available.
        return ConnectionStatus.NotConnected;
    }

    return ConnectionStatus.Connected;
}

The question is, how do I get it to not try the connection to Google (thus avoiding the dependency on the internet being up).

The easiest way is to take _google and change it to point to something local to the machine. But to do that I need to make _google public. I would rather not do that because _google should not ever be changed by the app.

I could make `_google' a param to an overloaded version of the method (or object constructor). But that too exposes an interface that I don't ever want the app to use.

The other option is to make _google internal. But for the app, internal is the same as public. So, while others cannot see _google, the app interface still exposes it.

Is there a better way? If so, please state it.

(Also, please don't pick on my example unless it really helps figure out a solution. I am asking for ideas on general scenarios like this, not necessarily this exact example.)


Refactor your code to depend on an ICommunicationChecker:

public interface ICommunicationChecker
{
    ConnectionStatus GetConnectionStatus();
}

Then your test(s) can mock this interface making the implementation details irrelevant.

public class CommunicationChecker : ICommunicationChecker
{
    private string _google = @"http://www.google.com";

    public ConnectionStatus GetConnectionStatus()
    {
        //Test if we can get to Google (A happy website that should always be there).
        Uri googleURI = new Uri(_google);
        if (!IsUrlReachable(googleURI, mGoogleTestString))
        {
            //The internet is not reachable.  No connection is available.
            return ConnectionStatus.NotConnected;
        }

        return ConnectionStatus.Connected;
    }
}


Why do you have _google hard coded in your code? Why not put it in a configuration file which you can then change for your test for example?


Some options:

  • make _google load from an external configuration (maybe providing www.google.com as a default value) and supply a special configuration for unit tests;
  • place the unit test class inside the class containing the CheckCommunicationLink method.

Note: I would strongly recommend making it configurable. In real-world cases relying on the availability of a particular 3rd party web site is not a good idea, because they can be blocked by a local firewall etc.


For unit testing purposes you should mock whatever http connection you are using in your class (which is hidden in IsUrlReachable method). This way you can check that your code is really trying to connect to google without actually connecting. Please paste the IsUrlReachable method if you need more help with mocking.

If the above solution is not an option, you could consider having a local test http server and:

  1. Making the url configurable, so that you can point to the local address
  2. (this one is nasty) Use reflection to change _google before the tests
  3. (most purist will disagree here) You could create an overload taking the parameter and use this one for testing (so you test only CheckCommunicationLink(string url) method

code for (3):

private string _google = @"http://www.google.com";

public ConnectionStatus CheckCommunicationLink()
{
    return CheckCommunicationLink(_google);
}

public ConnectionStatus CheckCommunicationLink(string url)
{
    //Test if we can get to Google (A happy website that should always be there).
    Uri googleURI = new Uri(url);
    if (!IsUrlReachable(googleURI, mGoogleTestString))
    {
        //The internet is not reachable.  No connection is available.
        return ConnectionStatus.NotConnected;
    }

    return ConnectionStatus.Connected;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜