我正在尝试对执行相当复杂操作的方法进行单元测试,但我已经能够将该操作分解为可模拟接口上的多个步骤,如下所示:
public class Foo
{
public Foo(IDependency1 dp1, IDependency2 dp2, IDependency3 dp3, IDependency4 dp4)
{
...
}
public IEnumerable<int> Frobnicate(IInput input)
{
var step1 = _dependency1.DoSomeWork(input);
var step2 = _dependency2.DoAdditionalWork(step1);
var step3 = _dependency3.DoEvenMoreWork(step2);
return _dependency4.DoFinalWork(step3);
}
private IDependency1 _dependency1;
private IDependency2 _dependency2;
private IDependency3 _dependency3;
private IDependency4 _dependency4;
}
我正在使用模拟框架 (Rhino.Mocks) 来生成模拟以进行测试,并且以此处显示的方式构建代码到目前为止非常有效。但是,我如何对这种方法进行单元测试,而无需每次都需要设置每个模拟对象和每个期望的大型测试呢?例如:
[Test]
public void FrobnicateDoesSomeWorkAndAdditionalWorkAndEvenMoreWorkAndFinalWorkAndReturnsResult()
{
var fakeInput = ...;
var step1 = ...;
var step2 = ...;
var step3 = ...;
var fakeOutput = ...;
MockRepository mocks = new MockRepository();
var mockDependency1 = mocks.CreateMock<IDependency1>();
Expect.Call(mockDependency1.DoSomeWork(fakeInput)).Return(step1);
var mockDependency2 = mocks.CreateMock<IDependency2>();
Expect.Call(mockDependency2.DoAdditionalWork(step1)).Return(step2);
var mockDependency3 = mocks.CreateMock<IDependency3>();
Expect.Call(mockDependency3.DoEvenMoreWork(step2)).Return(step3);
var mockDependency4 = mocks.CreateMock<IDependency4>();
Expect.Call(mockDependency4.DoFinalWork(step3)).Return(fakeOutput);
mocks.ReplayAll();
Foo foo = new Foo(mockDependency1, mockDependency2, mockDependency3, mockDependency4);
Assert.AreSame(fakeOutput, foo.Frobnicate(fakeInput));
mocks.VerifyAll();
}
这似乎非常脆弱。对 Frobnicate 实现的任何更改都会导致此测试失败(例如将步骤 3 分解为 2 个子步骤)。这是一种一体化的东西,因此尝试使用多个较小的测试是行不通的。它开始为未来的维护者提供只写代码,下个月我也忘记了它是如何工作的。一定有更好的方法!对?