【问题标题】:How to test for exceptions thrown using xUnit, SubSpec and FakeItEasy如何使用 xUnit、SubSpec 和 FakeItEasy 测试抛出的异常
【发布时间】:2012-06-13 10:32:29
【问题描述】:

我使用 xUnit、SubSpec 和 FakeItEasy 进行单元测试。 到目前为止,我已经创建了一些积极的单元测试,如下所示:

"Given a Options presenter"
    .Context(() =>
        presenter = new OptionsPresenter(view,
                                         A<IOptionsModel>.Ignored,
                                         service));

"with the Initialize method called to retrieve the option values"
    .Do(() => 
        presenter.Initialize());

"expect the view not to be null"
    .Observation(() =>
        Assert.NotNull(view));

"expect the view AutoSave property to be true"
    .Observation(() => Assert.True(view.AutoSave));

但是现在我想写一些负面的单元测试并检查某些方法没有被调用,并抛出异常

例如

"Given a Options presenter"
    .Context(() =>
        presenter = new OptionsPresenter(view,
                                         A<IOptionsModel>.Ignored,
                                         service));

"with the Save method called to save the option values"
    .Do(() => 
        presenter.Save());

"expect an ValidationException to be thrown"
    .Observation(() =>
        // TODO 
     );

"expect an service.SaveOptions method not to be called"
    .Observation(() =>
        // TODO 
     );

我可以看到 FakeItEasy 有一个 MustNotHaveHappened 扩展方法,而 xUnit 有一个 Assert.Throws 方法。

但是我该如何把它们放在一起呢?

我要测试的异常应该在调用 Save 方法时发生。所以我猜我应该在 presenter.Save() 方法调用周围包装一个 Assert.Throws 方法,但我认为应该在 .Do(() => ...

中调用 presenter.Save 方法

您能否告知我的单元测试是否应该如下所示或其他?

"Given a Options presenter"
    .Context(() =>    
        presenter = new OptionsPresenter(view,
                                         model,
                                         service));

"expect the Presenter.Save call to throw an Exception"
    .Observation(() =>
        Assert.Throws<FluentValidation.ValidationException>(() => presenter.Save()));

"expect the Service.SaveOptions method not to be called"
    .Observation(() =>
        A.CallTo(() => service.SaveOptions(A<IOptionsModel>.Ignored)).MustNotHaveHappened());

非常感谢

【问题讨论】:

标签: c# unit-testing bdd xunit fakeiteasy


【解决方案1】:

我没有听说过 FakeItEasy 或 SubSpec(你的测试看起来很时髦,所以我可能会检查一下 :))。但是,我确实使用 xUnit,所以这可能会有所帮助:

我将 Record.Exception 与 Assert.ThrowsDelegate 一起使用

比如:

    [Fact]
    public void Test()
    {
        // Arange

        // Act
        Exception ex = Record.Exception(new Assert.ThrowsDelegate(() => { service.DoStuff(); }));

        // Assert
        Assert.IsType(typeof(<whatever exception type you are looking for>), ex);
        Assert.Equal("<whatever message text you are looking for>", ex.Message);
    }

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    我会这样做:

    "Given a Options presenter"
        .Context(() =>
            presenter = new OptionsPresenter(view,
                                             (IOptionsModel)null,
                                             service));
    
    "with the Save method called to save the option values"
        .Do(() => 
            exception = Record.Exception(() => presenter.Save()));
    
    "expect an ValidationException to be thrown"
        .Observation(() =>
            Assert.IsType<ValidationException>(exception)
         );
    
    "expect an service.SaveOptions method not to be called"
        .Observation(() =>
            A.CallTo(() => service.SaveOptions(A<IOptionsModel>.Ignored)).MustNotHaveHappened()
         );
    

    或者更好的是,将 SubSpec 切换为 xBehave.net 并引入 FluentAssertions:-

    "Given an options presenter"
        .x(() => presenter = new OptionsPresenter(view, (IOptionsModel)null, service));
    
    "When saving the options presenter"
        .x(() => exception = Record.Exception(() => presenter.Save()));
    
    "Then a validation exception is thrown"
        .x(() => exception.Should().BeOfType<ValiationException>());
    
    "And the options model must not be saved"
        .x(() => A.CallTo(() =>
            service.SaveOptions(A<IOptionsModel>.Ignored)).MustNotHaveHappened());
    

    【讨论】:

      【解决方案3】:

      这是 FakeItEasy 中的一种方法。

      Action act = () => someObject.SomeMethod(someArgument);
      act.ShouldThrow<Exception>();
      

      【讨论】:

      • 我收到“Action 不包含 ShouldThrow 的定义...”我需要包含哪些参考/程序集?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-03
      • 2023-03-20
      • 2019-03-16
      • 2020-06-22
      • 2013-07-17
      • 2020-08-18
      相关资源
      最近更新 更多