我正在尝试对执行相当复杂的操作的方法进行单元测试,但是我已经能够将这个操作分解为可模拟接口上的许多步骤,如下所示:
public class Foo { public Foo(IDependency1 dp1, IDependency2 dp2, IDependency3 dp3, IDependency4 dp4) { ... } public IEnumerableFrobnicate(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(); Expect.Call(mockDependency1.DoSomeWork(fakeInput)).Return(step1); var mockDependency2 = mocks.CreateMock (); Expect.Call(mockDependency2.DoAdditionalWork(step1)).Return(step2); var mockDependency3 = mocks.CreateMock (); Expect.Call(mockDependency3.DoEvenMoreWork(step2)).Return(step3); var mockDependency4 = mocks.CreateMock (); 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个子步骤).这是一种一体化的东西,因此尝试使用多个较小的测试是行不通的.它开始接近未来维护者的只写代码,下个月当我忘记它是如何工作的时候,我自己也会这样做.一定有更好的方法!对?
单独测试IDependencyX的每个实现.然后,您将知道该过程的每个步骤都是正确的.单独测试时,测试每个可能的输入和特殊条件.
然后使用IDependencyX的实际实现进行Foo的集成测试.然后您就会知道所有单个部件都已正确插入.通常只需要测试一个输入,因为您只测试简单的胶水代码.