35

在我在 Nunit 中的测试程序中,我想通过验证消息来验证它是否收到了 write Argument Exception。

    [Test]
    public void ArgumentsWorkbookNameException()
    {
        const string workbookName = "Tester.xls";
        var args = new[] { workbookName, "Sheet1", "Source3.csv", "Sheet2", "Source4.csv" };
        Assert.Throws(typeof(ArgumentException), delegate { var appargs = new ApplicationArguments(args); }, "Invalid ending parameter of the workbook. Please use .xlsx");

    }

经过测试,当我在主程序中修改消息时,这不起作用。

        int wbLength = args[0].Length;

        // Telling the user to type in the correct workbook name file.
        if (args[0].Substring(wbLength-5,5)!=".xlsx")
        {
            throw new ArgumentException(
                "Invalid ending parameter of the workbook. Please use .xlsx random random");
        }

不管我是否更改了消息,单元测试仍然通过。

我该怎么做?或者C#中没有这样的东西。我的同事说在 Ruby 和 RSPEC 中有类似的选项,但他对 C# 不是 100% 确定。

4

4 回答 4

61

使用 fluent 接口创建断言:

Assert.That(() => new ApplicationArguments(args), 
    Throws.TypeOf<ArgumentException>()
        .With.Message.EqualTo("Invalid ending parameter of the workbook. Please use .xlsx random random"));
于 2015-01-14T18:17:44.090 回答
31

我同意乔恩的观点,“这样的测试不必要地脆弱”。但是,至少有两种方法可以检查异常消息:

1:Assert.Throws返回异常,因此您可以对其消息进行断言:

var exception = Assert.Throws<ArgumentException>(() => new ApplicationArguments(args));
Assert.AreEqual("Invalid ending parameter of the workbook. Please use .xlsx random random", exception.Message);

2: [HISTORICAL] 在 NUnit 3 之前,你也可以使用ExpectedException属性。但是,请注意,属性在整个测试代码中等待异常,而不仅仅是在抛出异常的代码中。因此,不建议使用此属性。

[Test]
[ExpectedException(typeof(ArgumentException), ExpectedMessage = "Invalid ending parameter of the workbook. Please use .xlsx random random")]
public void ArgumentsWorkbookNameException()
{
    const string workbookName = "Tester.xls";
    var args = new[] { workbookName, "Sheet1", "Source3.csv", "Sheet2", "Source4.csv" };
    new ApplicationArguments(args);
}
于 2013-07-23T17:03:02.177 回答
4

中的 message 参数Assert.Throws不是预期的异常消息;如果测试失败,这是包含在断言失败中的错误消息。

我不相信 NUnit 支持开箱即用地测试异常消息,而且我认为这样的测试无论如何都是不必要的脆弱。如果您真的想编写自己的此类辅助方法,您可以这样做,但我个人不鼓励这样做。(我也很少指定测试失败消息,除非它包含一些诊断信息。如果测试失败,我无论如何都会查看测试,所以消息不会增加太多。)

为简单起见,我鼓励您改用泛型重载和 lambda 表达式:

Assert.Throws<ArgumentException>(() => new ApplicationArguments(args));

(如果那是你的实际代码,还有其他问题 - 尝试new[] { "xyz" }作为参数传入......)

于 2013-07-23T16:54:48.813 回答
0

在 .NET Core 3.1 MSTest 项目中,我就是这样做的。

[TestMethod]
public async Task SaveItemAsync_NameIsNull_ThrowsException()
{
    var item = new Item
    {
        Name = null
    };

    var result = await Assert.ThrowsExceptionAsync<ArgumentException>(() => _service.SaveItemAsync(item));
    Assert.AreEqual("The item's name must be set.", result.Message);
}
于 2021-04-20T11:38:38.703 回答