Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement XUnit descriptive Assert message?

Context

in XUnit github I found this: Add Assert.Equal(expected, actual, message) overload #350 (so a developer ask for a non existing overload see below)

Quote from the answer:

We are a believer in self-documenting code; that includes your assertions.

(so the XUnit team rejects it)

OK, I got it. I also believe the self documenting code. Still I can not find out this use case:

Sample

// 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 

Question

How can I implement a descriptive assert message in this case in XUnit which still has no such an overload?

like image 771
g.pickardou Avatar asked Feb 13 '17 11:02

g.pickardou


People also ask

How do you write assert message?

There are two components to the use of assertion messages: Test readability (how easy it is to understand what the test is doing). Ease of diagnostics (how easy it is to understand why the test fails during a CI build).

What is xUnit assert?

In xUnit and many other testing frameworks, assertion is the mean that we conduct our test. In other word we assert an expectation that something is true about a piece of code. There are many different types of assertion in xUnit that we can use.


2 Answers

Use the suggestions provided at the link. Like fluent assertions or create your own assertion that wraps the Assert.True or Assert.False which were left with their message overloads. It was mentioned further down

Quote

You can provide messages to Assert.True and .False. If you simply cannot live without messages (and refuse to use a different assertion), you could always fall back to:

Assert.True(number == 2, "This is my message"); 

Quote:

If you really want to have messages you could add Fluent Assertions or maybe xbehave to your test projects and use their syntax. Fluent Assertions even throws xunit.net exceptions if it encounters its presence.

like image 73
Nkosi Avatar answered Sep 22 '22 17:09

Nkosi


I was having the same issue. I've a test that pulls data from two web api's and then compares and asserts various things about the content. I started using standard XUnit assertions like:

Assert.Equal(HttpStatusCode.OK, response1.StatusCode); Assert.Equal(HttpStatusCode.OK, response2.StatusCode); 

But whilst this gives a useful message that a 404 has been returned, it not clear from the logs on our build/CI server which service caused the error message.

I ended up adding my own assertion to give context:

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);         }     } } 

Then I can do the same assertions as:

AssertX.Equal(HttpStatusCode.OK, response1.StatusCode, $"Fetching {Uri1}"); AssertX.Equal(HttpStatusCode.OK, response2.StatusCode, $"Fetching {Uri2}"); 

and the error log gives the actual,expected and prepends my message about which webapi was the culprit.

I realise I'm late to answer, but figured this might help others searching for a practical solution that don't have time to install/learn yet another test framework just to get useful information out of test failures.

like image 37
Grhm Avatar answered Sep 21 '22 17:09

Grhm