在c#中引发了断言事件的扩展方法

时间:2017-02-23 13:25:09

标签: c# unit-testing events extension-methods assert

现在我正在这样做

bool didFire = false;
_viewModel.SomethingChanged = () => didFire = true;

_viewModel.SomeProperty = SomeValue;
Assert.IsTrue(didFire);

这有缺点:

  • 设置很丑,很长。
  • 每次拨打多个电话时,我都需要手动将didFire重置为false ,例如,如果我想在某些情况下测试该事件,但并非总是如此,遵循某种情况。这很容易出错,因为忘记它可能会破坏测试。
  • 对于许多事件/回调/情况,这会导致更多的样板代码用于测试简单事件。

就像任何体面的程序员一样,在看到自己重复同样的任务之后,我想将它存储在一个函数中。

我提出的最好的想法是将它放在Assert扩展方法中,但我找不到一个像样的方式,无论是我自己还是在线,以使其工作并仍然很好。

理想情况下,我正在寻找可以按照以下方式工作的内容

Assert.WillBeRaised(_viewModel.SomethingChanged);
_viewmodel.SomeProperty = SomeValue;

或者,或许只是反过来

_viewmodel.SomeProperty = SomeValue;
Assert.WasRaised(_viewModel.SomethingChanged);

这就是我的问题所在,有人必须在事件发生之前监听,并且断言必须在之后完成。无论如何,我觉得我最终会得到太多代码。

有没有人对这个相当常见的问题有一些干净的解决方案?

2 个答案:

答案 0 :(得分:2)

您可能需要查看Fluent Assertions

通过这些,您可以执行以下操作:

// this is the whole initialization
_viewModel.MonitorEvents();

// do test
_viewModel.SomeProperty = SomeValue;

// this is the whole assertion
_viewModel.ShouldRaise("SomethingChanged");

您可以对此进行扩展以检查传递给事件处理程序等的参数:

_viewModel.ShouldRaise("SomethingChanged")
          .WithSender(_viewModel)
          .WithArgs<SomethingChangedEventArgs(e => e.Name == "SomeValue");

答案 1 :(得分:1)

你可以这样写:

    public static void WillBeRaised(Action<Action> attach, Action act)
    {
        bool called = false;
        attach(() => called = true);
        act();
        Assert.IsTrue(called);
    }

用法:

   WillBeRaised(
        x => _viewmodel.SomethingChanged += x, 
        () => _viewmodel.SomeProperty = SomeValue);