如何实现XUnit描述性断言消息?

g.p*_*dou 26 c# unit-testing xunit assertions xunit2

上下文

在XUnit github中我发现了这个:添加Assert.Equal(预期,实际,消息)重载#350 (所以开发人员要求不存在的重载请参见下文)

引用答案:

我们相信自我记录的代码; 包括你的断言.

(所以XUnit团队拒绝它)

好,我知道了.我也相信自我记录代码.我还是找不到这个用例:

样品

// Arrange
// Create some external soap service client and its wrapper classes

// Act
// client.SomeMethod();

// Assert
// Sorry, soap service's interface, behaviour and design is *given*
// So I have to check if there is no Error, and 
// conveniently if there is, then I would like to see it in the assertion message

Assert.Equal(0, client.ErrorMessage.Length); // Means no error

// I would like to have the same result what would be the following *N*U*n*i*t* assert:
// Assert.AreEqual(0, client.ErrorMessage.Length, client.ErrorMessage); // Means no error
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如何在XUnit中实现描述性断言消息仍然没有这样的重载?

Nko*_*osi 16

使用链接提供的建议.像流畅的断言或创建自己的断言,包裹Assert.True or Assert.False留下他们的消息超载.它被进一步提到了

引用

您可以向Assert.True和.False提供消息.如果你根本不能没有消息(并且拒绝使用不同的断言),你总是可以回到:

Assert.True(number == 2, "This is my message");
Run Code Online (Sandbox Code Playgroud)

引用:

如果你真的想要有消息,可以 在测试项目中添加Fluent Assertionsxbehave并使用它们的语法.Fluent Assertions甚至会在遇到其存在时抛出xunit.net异常.

  • @TabsNotSpaces 虽然您的建议 * 确实* 有所改善,但您仍然会收到一条更长的消息,其中包含 2 组预期/实际值对:“`这是我的消息 <newline> 预期:2 <newline> 实际:1 <newline> 预期:True <newline> 实际:False`"。感谢您的建议 :) 对 Xunit 表示敬意,实际上,无论他们希望如何自以为是,恕我直言,“自记录代码”与我们 CI/CD 管道日志上的单元测试输出无关…… :) (3认同)
  • 退回到`Assert.True(number == 2,“这是我的消息”);`会导致更加模糊的消息,其中隐藏了已比较的实际值:“`这是我的消息<newline>预期:True <newline>实际:False`”,所以这不是一个真正的选择(当然,我不是在@Nkosi向您抱怨,只是认为应该指出这一点:)) (2认同)

Pet*_*r L 10

使用try/catch就足以满足我的目的:

try
{
    Assert.Equal(expectedErrorCount, result.Count);
}
catch (EqualException ex)
{
    throw new XunitException($"{testMsg}\n{ex}");
}
Run Code Online (Sandbox Code Playgroud)


Grh*_*rhm 6

我有同样的问题。我有一个测试,该测试从两个Web API提取数据,然后比较并声明有关内容的各种信息。我开始使用标准的XUnit断言,例如:

Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
Assert.Equal(HttpStatusCode.OK, response2.StatusCode);
Run Code Online (Sandbox Code Playgroud)

但是,尽管这给出了一条有用的消息,表明已返回404,但从我们的build / CI服务器上的日志中看不出来是哪个服务导致了错误消息。

我最终添加了自己的断言来提供上下文:

public class MyEqualException : Xunit.Sdk.EqualException
{
    public MyEqualException(object expected, object actual, string userMessage)
        : base(expected, actual)
    {
        UserMessage = userMessage;
    }

    public override string Message => UserMessage + "\n" + base.Message;
}

public static class AssertX
{
    /// <summary>
    /// Verifies that two objects are equal, using a default comparer.
    /// </summary>
    /// <typeparam name="T">The type of the objects to be compared</typeparam>
    /// <param name="expected">The expected value</param>
    /// <param name="actual">The value to be compared against</param>
    /// <param name="userMessage">Message to show in the error</param>
    /// <exception cref="MyEqualException">Thrown when the objects are not equal</exception>
    public static void Equal<T>(T expected, T actual, string userMessage)
    {
        bool areEqual;

        if (expected == null || actual == null)
        {
            // If either null, equal only if both null
            areEqual = (expected == null && actual == null);
        }
        else
        {
            // expected is not null - so safe to call .Equals()
            areEqual = expected.Equals(actual);
        }

        if (!areEqual)
        {
            throw new MyEqualException(expected, actual, userMessage);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我可以执行与以下相同的断言:

AssertX.Equal(HttpStatusCode.OK, response1.StatusCode, $"Fetching {Uri1}");
AssertX.Equal(HttpStatusCode.OK, response2.StatusCode, $"Fetching {Uri2}");
Run Code Online (Sandbox Code Playgroud)

错误日志给出了实际的,预期的信息,并在提示我之前提示了哪个webapi是元凶。

我意识到我来不及回答,但认为这可能会帮助其他人寻找实用的解决方案,而这些解决方案没有时间安装/学习另一个测试框架,只是为了从测试失败中获取有用的信息。

  • 我开始想知道我选择 xUnit 而不是 MSTest 是否做得好。后者提供了更好的断言选项。对此有什么想法吗? (6认同)

Gau*_*ssZ 5

我偶然发现了同样的问题,令我惊讶的是,即使 6 年后,仍然没有人遵循这个建议来编写自定义断言方法。所以我自己在这里写了一篇。

只需添加 nuget 包并为AssertM类添加别名,如下所示:

using Assert = XunitAssertMessages.AssertM;
Run Code Online (Sandbox Code Playgroud)

所有先前的 xunit 断言方法都可用,因此当前断言将继续编译,但添加了可选消息参数。

// This will work
Assert.Equal(0, client.ErrorMessage.Length)
// and so will this
Assert.Equal(0, client.ErrorMessage.Length, "Unexpected length")
Run Code Online (Sandbox Code Playgroud)