我有一个问题,我的测试大部分 都通过了,但偶尔会失败。我认为这可能是一个线程问题,但我已经尝试使用锁和 sleep 等来尝试找出问题所在,但没有成功。我使用的语法正确吗?离开一段时间后,我又开始使用 Rhino。
这是我的测试的净化版本。就像我说的,他们 4 次中有 3 次工作,但随后繁荣。
[TestFixture]
public class Tests
{
[Test]
public void ReprocessItems()
{
// Arrange
Presenter presenter = new Presenter();
Model model = new Model();
model.Data.Add(new ViewModel(new Item { Id = 1 }) { IsSelected = true });
model.Data.Add(new ViewModel(new Item { Id = 2 }) { IsSelected = true });
model.Data.Add(new ViewModel(new Item { Id = 3 }) { IsSelected = false });
model.Data.Add(new ViewModel(new Item { Id = 4 }) { IsSelected = false });
presenter.Model = model;
var gateway = MockRepository.GenerateStub<IGateway>();
presenter.Gateway = gateway;
// Act
presenter.ReprocessItems();
// Assert
gateway.AssertWasCalled(o => o.ReprocessItem(1, presenter.ReprocessDone));
gateway.AssertWasCalled(o => o.ReprocessItem(2, presenter.ReprocessDone));
}
[Test]
public void ShowItemReferralCommentary()
{
// Arrange
Presenter presenter = new Presenter();
Model model = new Model();
model.Data.Add(new ViewModel(new Item { Id = 1 }) { IsSelected = true });
model.Data.Add(new ViewModel(new Item { Id = 2 }) { IsSelected = false });
presenter.Model = model;
var gateway = MockRepository.GenerateStub<IGateway>();
presenter.Gateway = gateway;
var view = MockRepository.GenerateStub<IView>();
presenter.View = view;
gateway.Stub(x => x.RequestItemCommentary(1)).Return("This is some commentary");
// Act
presenter.ShowItemReferralCommentary();
// Assert
gateway.AssertWasCalled(o => o.RequestItemCommentary(1));
view.AssertWasCalled(o => o.ShowMessageBox("This is some commentary", "Referral Commentary"));
}
[Test]
public void AcceptSelectedItems()
{
// Arrange
Presenter presenter = new Presenter();
Model model = new Model();
model.Data.Add(new ViewModel(new Item { Id = 1 }) { IsSelected = false });
model.Data.Add(new ViewModel(new Item { Id = 2 }) { IsSelected = false });
model.Data.Add(new ViewModel(new Item { Id = 3 }) { IsSelected = true });
model.Data.Add(new ViewModel(new Item { Id = 4 }) { IsSelected = true });
presenter.Model = model;
var gateway = MockRepository.GenerateStub<IGateway>();
presenter.Gateway = gateway;
// Act
presenter.AcceptSelectedItems();
// Assert
gateway.AssertWasCalled(o => o.AcceptItem(3, presenter.AcceptCompleted));
gateway.AssertWasCalled(o => o.AcceptItem(4, presenter.AcceptCompleted));
}
}
编辑:** 根据下面的评论,我通过添加 Thread.Sleep(500); 暂时解决了这个问题在每个断言之前。 Thread.Sleeps 通常是一种代码味道,我想将其锁定,但我正在努力做到马虎 务实。如果您有更好的方法,请告诉我。
最佳答案
问题是您可能会到达测试方法的末尾,也就是您放置断言的位置,而子线程可能已经完成了它们的工作,也可能没有。在您看来,这几乎是随机的。
您可以做的,也是我在测试线程方法时所做的,是使用同步对象,例如 ManualResetEvent。您在测试方法开始时将其重置为 false:
var wait = new ManualResetEvent(false);
然后,当被测试的对象调用您的 mock 时,您设置它的状态:
Expect.Call(() => yourMock.yourMethod(whatever)).WhenCalled(x => wait.Set() );
现在,在你的断言 block 代码之前,你写一些像
Assert(wait.WaitOne(timeoutOfYourChoice));
这将为辅助线程留出足够的时间来完成它们的工作。
关于c# - Rhino Mocks AAA 语法和线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4224335/