c# - Rhino Mocks AAA 语法和线程安全

标签 c# unit-testing rhino-mocks

我有一个问题,我的测试大部分 都通过了,但偶尔会失败。我认为这可能是一个线程问题,但我已经尝试使用锁和 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/

相关文章:

.net - 如何清除之前对某个对象的期望?

c# - 检查 MySQL 数据库中是否存在用户失败

c++ - 使用 Google Mocks,如何在不关心/设置任何调用期望的情况下给出模拟实现

c# - C# 中模态形式和非模态形式有什么区别?

spring - 如何使用 Spring 4 和注释编写单元测试来验证异步行为?

unit-testing - 在 Istanbul 尔覆盖范围中排除模式或文件夹

rhino-mocks - 我可以让Rhino MocksGenerateStub或GenerateMock每次都返回一个新类型吗?

c# - 使用 Rhino Mocks 获取属性

c# - 从父级的任何子控件捕获击键

c# - 为什么 SortedList 和 List 使用数组,为什么 LinkedList 用得不多?