1

I have a service class, it creates a new concrete PropertyClass, before doing action. I'm trying to test if DoSomething() was run. Is it possible to create stud and control the returned Property value to a mock object?

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());
}
4

2 回答 2

1

不,但是您可以使用工厂设计模式轻松缓解此问题。考虑:

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());
}

请注意,当 factory如此简单时,您最好使用Func<IPropertyClass>而不是创建额外的类/接口对。

于 2013-06-17T12:29:50.257 回答
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();
}
于 2013-06-17T12:25:08.637 回答