如何测试使用 xUnit、SubSpec 和 FakeItEasy 引发的异常

本文关键字:FakeItEasy SubSpec 异常 xUnit 何测试 测试 | 更新日期: 2023-09-27 18:36:56

我正在使用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有一个MustNotHaveHappen扩展方法,xUnit有一个Assert.Throws方法。

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

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

你能告诉我我的单元测试应该看起来像下面还是其他什么吗?

"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());

非常感谢

如何测试使用 xUnit、SubSpec 和 FakeItEasy 引发的异常

我没有听说过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);
    }

希望有帮助。

我会这样做:

"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()
     );

或者更好的是,将子规范切换为 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());

这是在FakeItEasy中执行此操作的一种方法。

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