如何使用Rhino Mocks for Stream?

时间:2011-09-06 19:24:28

标签: unit-testing rhino-mocks

我正在进行文件转换,这是多步骤的过程。 STEAP1的输出作为STEP2的输入传递。 STEP2的输出是最终输出,它分配回Context.FinalOutput属性。由于最终输出是Stream,我希望调用者决定使用哪个流。这就是为什么调用者将传递Stream作为上下文的一部分。 我只想知道,我用Rhino Mocks编写的测试是否正确?

namespace Test
{
    public interface IContextInfo
    {
        // Input parameters here

        // Output parameter
        Stream FinalOutput { get; set; }
    }

    public interface IStep1
    {
        void DoStep1(IContextInfo contextInfo, Stream outputOfStep1);
    }

    public interface IStep2
    {
        void DoStep2(Stream outputOfStep1, Stream outputOfStep2);
    }

    public interface IController
    {
        void Execute();
    }

    public class MyController : IController
    {
        IContextInfo _contextInfo = null;
        IStep1 _step1 = null;
        IStep2 _step2 = null;

        public MyController(IContextInfo contextInfo, IStep1 step1, IStep2 step2)
        {
            _contextInfo = contextInfo;
            _step1 = step1;
            _step2 = step2;
        }

        public void Execute()
        {
            using (Stream outputOfStep1 = new MemoryStream())
            {
                this._step1.DoStep1(_contextInfo, outputOfStep1);
                this._step2.DoStep2(outputOfStep1, this._contextInfo.FinalOutput);
            }
        }
    }

    [TestClass]
    public class ControllerTests
    {
        [TestMethod]
        public void Controller_Execute()
        {
            MockRepository mock = new MockRepository();
            var context = mock.Stub<IContextInfo>();
            var step1 = mock.Stub<IStep1>();
            var step2 = mock.Stub<IStep2>();

            var outputOfStep1 = mock.StrictMock<Stream>();
            context.FinalOutput = mock.StrictMock<Stream>();

            step1.Expect(x => x.DoStep1(context, outputOfStep1)).IgnoreArguments();
            step2.Expect(c => c.DoStep2(outputOfStep1,context.FinalOutput)).IgnoreArguments();
            mock.ReplayAll();

            var controller = new MyController(context, step1, step2);
            controller.Execute();

            //Assert
            Assert.IsNotNull(controller);
            mock.VerifyAll();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

根据您的测试的组成方式,您的测试意图似乎是验证在_step1方法中正确调用了两个依赖项_step2Execute()的类。这是一个很好的第一次测试。

不幸的是,您的测试无法正确测试该情况。由于您要对_step1_step2设置期望值,因此需要将它们从存根更改为模拟。

此外,由于您没有对输出设置期望,因此您应该将它们更改为模拟中的存根或完全删除它们,因为您正在调用IgnoreArguments()

[TestMethod]
public void Execute_IsCalled_Step1AndStep2AreCalled() 
{
    //Arrange
    MockRepository mock = new MockRepository();
    var context = mock.Stub<IContextInfo>();

    var step1 = mock.StrictMock<IStep1>();
    var step2 = mock.StrictMock<IStep2>();

    step1.Expect(x => x.DoStep1(null, null)).IgnoreArguments();
    step2.Expect(c => c.DoStep2(null, null)).IgnoreArguments();
    mock.ReplayAll();

    //Act
    var controller = new MyController(context, step1, step2);
    controller.Execute();

    //Assert
    mock.VerifyAll();
}

为清晰起见,我做了一些额外的更改:

我重命名了您的方法以更恰当地描述测试。我通常遵循这样的模式:MethodUnderTest_Condition_ExpectedResult()。我也删除了Assert.IsNotNull(controller);,因为它不适用于正在测试的条件。

您可能想要针对此方法编写更多测试(例如,确保Step1的输出是Step2的输入)。最重要的是,请记住在测试中明确您正在测试的内容,并尽力一次测试一个条件。