【问题标题】:Rhino Mock to execute yield returnRhino Mock 执行收益回报
【发布时间】:2012-02-08 17:26:34
【问题描述】:

我正在尝试编写一个单元测试来检查解析错误。我正在从文件中流式传输数据,对其进行解析并使用 yield return 返回解析结果,然后将其传递给数据层以进行批量插入。

我无法模拟对数据层的调用。因为它被模拟了,所以它实际上从未从 yield return 中枚举值,因此我的解析方法永远不会执行。

public class Processor
{
    public IUnityContainer Container { get; set; }

    public void ProcessFile(Stream stream)
    {
        var datamanager = Container.Resolve<IDataManager>();                                            
        var things = Parse(stream);        
        datamanager.Save(things);                                
    }

    IEnumerable<string> Parse(Stream stream)
    {
        var sr = new StreamReader(stream);
        while (!sr.EndOfStream)
        {
            string line = sr.ReadLine();
            // do magic
            yield return line;
        }
    }
}

我尝试了类似的方法,但显然行不通。

[TestMethod]        
[ExpectedException(typeof(ApplicationException))]
public void ProcessFile_InvalidInput_ThrowsException()
{
    var mock = new MockRepository();

    var stream = new MemoryStream();
    var streamWriter = new StreamWriter(stream);                
    streamWriter.WriteLine("\\:fail");
    streamWriter.Flush();
    stream.Position = 0;

    var datamanager = mock.Stub<IDataManager>();                        
    TestContainer.RegisterInstance(datamanager);

    var repos = new ProcessingRepository();
    TestContainer.BuildUp(repos);

    using (mock.Record())
    {                         
        Expect.Call(file.InputStream).Return(stream);                            
        Expect.Call(delegate() { repos.Save(new List<string>()) }).IgnoreArguments();
    }
    using (mock.Playback())
    {
        repos.ProcessFile(stream);
    }
}

【问题讨论】:

    标签: c# ienumerable rhino-mocks yield-return


    【解决方案1】:

    一个最佳解决方案是将“//do magic”中发生的事情放在一个单独的方法中,这样它就可以单独进行单元测试——而不需要从正在处理流阅读器。

    您看到的问题是由于对枚​​举的惰性评估。由于您的测试代码实际上都没有枚举“事物”,因此永远不会处理“幕后”构建以处理迭代器块的状态机。

    您需要枚举项目才能实际执行 Parse 方法中的逻辑。您可以使用 Rhino.Mocks "WhenCalled" 方法执行此操作(我正在显示 AAA 语法,因为我不记得如何使用记录/重播语义):

    注意:这是未经测试的代码

    datamanager.Stub(d => d.Save(null)).IgnoreArguments().WhenCalled(m => int count = ((IEnumerable<string>)m.Arguments[0]).Count());
    

    当调用存根上的 Save 方法时,会向“WhenCalled”传递一个参数 (m),其中包含有关所调用方法的信息。获取第一个参数(事物),将其转换为 IEnumerable&lt;string&gt; 并获取其计数。这将强制对可枚举进行评估。

    【讨论】:

    • WhenCalled 正是我想要的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-05-27
    • 2012-01-14
    • 1970-01-01
    • 2018-01-23
    • 2010-12-01
    • 1970-01-01
    • 2011-01-13
    相关资源
    最近更新 更多