如何模拟新创建的对象?

时间:2017-03-30 15:50:34

标签: c# unit-testing mocking

非常简化的代码版本:

interface IFactory
{
    ITreasure Get(SomeData data);
}

class Factory : IFactory
{
    ITreasure Get(SomeData data)
    {
         // Create instance of ITreasure in very long chain of methods basing on "data"
         // Can produce one of: BlueTreasure, RedTreasure or GreenTreasure
         return treasure;
    }
}

就是这样,有气味的课程我不能完全修改。

class CantModify
{
    public CantModify {}

    public TestMe(SomeData data)
    {
        ITreasure treasure = new Factory().Get(data);

        if(treasure is BlueTreasure) ...
        else if(treasure is RedTreasure) ...
        else if(treasure is GreenTreasure) ...
    }
}

我想测试 TestMe()的所有代码路径,但我不想准备数据来获取特定类型的ITreasure。 有没有办法让新的Factory()返回工厂的Mocked实例,它会在每次测试中返回不同类型的ITreasure?

2 个答案:

答案 0 :(得分:1)

您需要在Cantmodify类中添加对IFactory的依赖。然后你可以模拟Get Method返回你想要的任何东西。 该课应该看起来:

public class CantModify
{
    private readonly IFactory _factory;

    public CantModify(IFactory factory)
    {
        _factory = factory;
    }

     public TestMe(SomeData data)
    {
        ITreasure treasure = _factory.Get(data);

        if (treasure is BlueTreasure) ...


    else if (treasure is RedTreasure) ...

    else if (treasure is GreenTreasure) ...

} 

答案 1 :(得分:1)

您可以模拟Factory的所有未来实例,并且您将能够修改Get方法的行为以适合您的测试,例如我使用Typemock隔离器来创建测试检查treasure是否为绿色:

 public string TestMe(SomeData data)
 {
     ITreasure treasure = new Factory().Get(data);

     if (treasure is BlueTreasure) { return "blue"; }
     else if (treasure is RedTreasure) { return "red"; }
     else if (treasure is GreenTreasure) { return "green"; }
     return null;
 }


 [TestMethod,Isolated]
public void TestMethod1()
{
    var fakeFactory = Isolate.Fake.AllInstances<Factory>();
    var green = new GreenTreasure();

    Isolate.WhenCalled(() => fakeFactory.Get(null)).WillReturn(green);

    var res = new CantModify().TestMe(new SomeData());

    Assert.AreEqual("green", res);
}