【发布时间】:2011-07-01 08:32:48
【问题描述】:
我们目前在单元测试期间遇到了一些问题。我们的类使用 Rhino Mocks 对 Mocked 对象的一些函数调用进行多线程处理。这是一个精简到最低限度的示例:
public class Bar
{
private readonly List<IFoo> _fooList;
public Bar(List<IFoo> fooList)
{
_fooList = fooList;
}
public void Start()
{
var allTasks = new List<Task>();
foreach (var foo in _fooList)
allTasks.Add(Task.Factory.StartNew(() => foo.DoSomething()));
Task.WaitAll(allTasks.ToArray());
}
}
接口IFoo定义为:
public interface IFoo
{
void DoSomething();
event EventHandler myEvent;
}
为了重现死锁,我们的单元测试执行以下操作: 1. 创建一些 IFoo 模拟 2. 在调用 DoSomething() 时引发 myEvent。
[TestMethod]
public void Foo_RaiseBar()
{
var fooList = GenerateFooList(50);
var target = new Bar(fooList);
target.Start();
}
private List<IFoo> GenerateFooList(int max)
{
var mocks = new MockRepository();
var fooList = new List<IFoo>();
for (int i = 0; i < max; i++)
fooList.Add(GenerateFoo(mocks));
mocks.ReplayAll();
return fooList;
}
private IFoo GenerateFoo(MockRepository mocks)
{
var foo = mocks.StrictMock<IFoo>();
foo.myEvent += null;
var eventRaiser = LastCall.On(foo).IgnoreArguments().GetEventRaiser();
foo.DoSomething();
LastCall.On(foo).WhenCalled(i => eventRaiser.Raise(foo, EventArgs.Empty));
return foo;
}
生成的 Foo 越多,死锁发生的频率就越高。如果测试不会阻塞,运行它几次,它会。 停止调试测试运行表明,所有任务仍处于 TaskStatus.Running 并且当前工作线程正在中断
[处于睡眠、等待或加入]
Rhino.Mocks.DLL!Rhino.Mocks.Impl.RhinoInterceptor.Intercept(Castle.Core.Interceptor.IInvocation 调用) + 0x3d 字节
最让我们困惑的是这样一个事实,即 Intercept(...) 方法的签名被定义为 Synchronized - 但这里有几个线程。我已经阅读了几篇关于 Rhino Mocks 和多线程的帖子,但没有发现警告(预计会设置记录)或限制。
[MethodImpl(MethodImplOptions.Synchronized)]
public void Intercept(IInvocation invocation)
我们在设置 Mockobject 或在多线程环境中使用它们时是否做错了什么?欢迎任何帮助或提示!
【问题讨论】:
-
我在我的谷歌旅行中发现了这个http://blog.smithfamily.dk/post/2011/03/26/Thread-safe-version-of-Rhino-Mocks.aspx。可悲的是,那里托管的版本似乎有一个错误,所以我看不到它是否解决了这个问题。
标签: c# multithreading unit-testing rhino-mocks deadlock