Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 如何使用犀牛模拟流?_Unit Testing_Rhino Mocks - Fatal编程技术网

Unit testing 如何使用犀牛模拟流?

Unit testing 如何使用犀牛模拟流?,unit-testing,rhino-mocks,Unit Testing,Rhino Mocks,我正在做文件转换,这是一个多步骤的过程。STEAP1的输出作为输入传递到步骤2。步骤2的输出是分配回Context.FinalOutput属性的最终输出。因为最终的输出是Stream,所以我希望调用者决定使用哪个流。这就是调用者将流作为上下文的一部分传递的原因。 我只是想知道,我用Rhino Mocks编写的测试是否正确 namespace Test { public interface IContextInfo { // Input parameters her

我正在做文件转换,这是一个多步骤的过程。STEAP1的输出作为输入传递到步骤2。步骤2的输出是分配回Context.FinalOutput属性的最终输出。因为最终的输出是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();
        }
    }
}

根据测试的组成方式,测试的目的似乎是验证在Execute方法中是否正确调用了两个依赖项_step1和_step2类。这是编写的第一个很好的测试

不幸的是,您的测试没有正确地测试该条件。由于您正在为_step1和_step2设置期望值,因此需要将它们从存根更改为模拟

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

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

我重命名了您的方法以更恰当地描述测试。我通常遵循以下模式:MethodUnderTest\u Condition\u ExpectedResult。我还删除了Assert.IsNotNullcontroller;因为它不特别适用于正在测试的条件


当然,您可能需要针对该方法编写更多的测试,例如,确保步骤1的输出是步骤2的输入。最重要的是,记住在测试中要清楚地知道你到底在测试什么,并尽最大努力一次测试一个条件。

你想测试什么?你有编译错误吗?运行测试时出错?
[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();
}