简体   繁体   中英

How do you create a mock/substitute when you don't want to expose an instance of a class?

Let's say I have the following class, LightbulbManager , that has a Lightbulb object. In its constructor, it loads a Lightbulb from an external resource, such as an XML file.

If I expose myLightbulb via a property, and that property is part of ILightbulbManager , then I could easily create a substitute for it. However, I don't want to expose myLightbulb to the end user of this API because they might modify the Lightbulb object. The alternative is to add an SetLightbulb() function, which I can use to set myLightbulb , but I don't want an end user to have that ability either.

So my question is, how do I actually unit test IsLightbulbOn() by creating a substitute for myLightbulb ? Or is this indicating to me that my code is poorly designed?

class LightbulbManager : ILightbulbManager
{
    private Lightbulb myLightbulb;

    public LightbulbManager()
    {
        // Loads lightbulb information from an external resource.
    }

    public bool IsLightbulbOn()
    {
        return myLightbulb.IsOn;
    }
}

You could create a ILightbulbFactory interface with two classes implementing the interface. One that creates the lightbulb from the external resource and the other one used in tests to create your substitute. Then you pass that factory to the LightbulbManager constructor.

public interface ILightbulbFactory
{
    Lightbulb MakeLightbulb();
}

public class LightbulbFactory : ILightbulbFactory
{
    public Lightbulb MakeLightbulb()
    {
        Do your external resource load and return the object...
    }
}

public class LightbulbFactoryForTests : ILightbulbFactory
{
    public Lightbulb MakeLightbulb()
    {
        Create your lightbulb for testing...
    }
}

in the constructor:

public LightbulbManager(ILightbulbFactory factory)
{
    myBulb = factory.MakeLightbulb();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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