是否可以为创建具体类创建存根?

时间:2013-06-17 12:21:09

标签: c# unit-testing rhino-mocks

我有一个服务类,它在执行操作之前创建一个新的具体PropertyClass。我正在尝试测试是否运行了DoSomething()。 是否可以创建stud并将返回的Property值控制为模拟对象?

public class ServiceClass
{
    public PropertyClass Property {set; get;}

    public void Action()
    {
        Property = new PropertyClass();

        Property.DoSomething();
    }
}
[Test] // This test does not work.
public class Action_Test
{
    var service = new ServiceClass();
    var mockPropertyClass = MockRepository.GenerateMock<IPropertyClass>();

    service.Property.Stub(x=> new PropertyClass()).Return(mockPropertyClass);

    service.Action();

    service.Property.AssertWasCalled(x => x.DoSomething());
}

2 个答案:

答案 0 :(得分:1)

您的Action方法正在创建自己的PropertyClass实例,它会覆盖您的存根。

public void Action()
{
    if (Property == null)
        Property = new PropertyClass();

    Property.DoSomething();
}

每次使用Property属性时必须检查的一个很好的方法是在构造函数中分配属性。

public ServiceClass() {
    Property = new PropertyClass();
}

然后Action方法就是:

public void Action()
{
    Property.DoSomething();
}

答案 1 :(得分:1)

没有。但您可以使用factory design pattern轻松缓解此问题。考虑:

public class ServiceClass
{
    private readonly IPropertyClassFactory factory;

    public PropertyClass Property { get; private set; }

    public ServiceClass(IPropertyClassFactory factory)
    {
        this.factory = factory;
    }

    public void Action()
    {
        Property = factory.CreateInstance();
        Property.DoSomething();
    }
}

在测试中,您创建模拟工厂,该工厂返回模拟对象。像这样:

[Test]
public class Action_Test
{
    var factoryMock = MockRepository.GenerateMock<IPropertyClassFactory>();
    var propertyMock = MockRepository.GenerateMock<IPropertyClass>();
    factoryMock.Stub(f => f.CreateInstance()).Returns(propertyMock);
    var service = new ServiceClass(factoryMock);

    service.Action();

    propertyMock.AssertWasCalled(x => x.DoSomething());
}

请注意,当工厂这个简单的时,您也可以使用Func<IPropertyClass>而不是创建额外的类/接口对。