2

我是使用 Mocking 框架来模拟对象以进行单元测试的新手。我目前正在使用 Rhino Mocks,我认为它会有一种方法来做我找不到的事情。这是一个 LinqPad 程序(只需将其复制并粘贴到 C# 程序查询中,它就可以工作),它显示了我正在尝试做的事情:

public interface MyTest{
    int A(int i);
    string B(int i);
}

/// This is an actual class that is a black box to me.
public class ActualClass : MyTest {
    public int A(int i){
        // Does some work
        return ++i;
    }

    public string B(int i){
        return A(i).ToString();
    }
}

/// I'd like to create a mocked class that uses an instance of the actual class 
/// to provide all of the implementations for the interface except for a single method
/// where I can check the parameter values, and provide my own return value, 
/// or just call the actual class
public class MockedClass : MyTest {

    private ActualClass _actual;
    public MockedClass(ActualClass actual){
        _actual = actual;
    }
    public int A(int i){
        if(i == 1){
            return 10;
        }else{
            return _actual.A(i);
        }
    }

    public string B(int i){
        return _actual.B(i);
    }
}

void Main()
{
    var mock = new MockedClass(new ActualClass());
    mock.A(0).Dump();
    mock.A(1).Dump();
    mock.A(2).Dump();
    mock.B(0).Dump();
    mock.B(1).Dump();
    mock.B(2).Dump();
}

结果:

1
10
3
1
2
3

我该怎么做才能模拟这个进行单元测试。我需要某种依赖注入器吗?

4

1 回答 1

1

是的,您可以根据传入的参数更改模拟对象的返回值。我不会采用混合真实依赖项和模拟依赖项的方法——真实依赖项中的错误有太多机会潜入到你的测试。

这是您可以在 MyTest 接口上使用的示例,它检查模拟方法的输入参数并相应地设置返回值:

var mock = MockRepository.GenerateStub<MyTest>();
mock.Stub(m => m.A(Arg<int>.Is.Anything))
    .Return(99)
    .WhenCalled(mi =>
                    {
                        var arg = Convert.ToInt32(mi.Arguments[0]);
                        switch (arg)
                        {
                            case 0:
                                mi.ReturnValue = 10;
                                break;
                            case 1:
                                mi.ReturnValue = 20;
                                break;
                            case 2:
                                mi.ReturnValue = 30;
                                break;
                            default:
                                mi.ReturnValue = -1;
                                break;
                        }
                    });

请注意,“Return(99)”是必需的,因为当您存根返回值的方法时,Rhino.Mocks要求您定义要抛出的异常或定义返回值。即使我们不使用返回值(因为我们在 WhenCalled 处理程序中提供了自己的返回值),它仍然必须定义,否则 Rhino.Mocks 将在第一次调用存根时抛出异常。

于 2012-08-08T17:51:43.017 回答