Rhino Mock执行收益回报
本文关键字:回报 收益 执行 Mock Rhino | 更新日期: 2023-09-27 18:24:00
我正在尝试编写一个单元测试来检查解析错误。我从一个文件流式传输数据,对其进行解析,并返回解析结果和yield return,然后将其传递到数据层进行大容量插入。
我很难模拟出对数据层的调用。因为它被嘲笑了,所以它从来没有实际枚举yield返回中的值,因此我的解析方法从来没有执行过。
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);
}
}
一个最佳解决方案是将"//do magic"中发生的事情放在一个单独的方法中,这样它就可以单独进行单元测试,而不需要从处理StreamReader的while循环内部调用。
您看到的问题是由于枚举的惰性评估。由于您的测试代码实际上都没有枚举"事物",因此永远不会处理"幕后"构建的用于处理迭代器块的状态机。
您需要枚举这些项,以便实际执行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<string>
并获取其计数。这将强制对枚举值进行评估。