[go: up one dir, main page]

Skip to content
Manuel Markwalder edited this page Jan 22, 2016 · 4 revisions

Extended Assertions (exas)

When writing unit tests, we often face the problem of verifying bigger object graphs. When in this situation we often tend to either do a poor verification of the object graph or to lose a serious amount of time on verifying it. Extended Assertion tries to ease up a complete verification of bigger objects and safe you time when writing and anylzing unit tests.

The dojo case

Let's take a concrete case to see what Extended Assertions can do for you - the dojo case. Our productive code declares a service method FindDojo(string) returning the following object graph:

dojo { name = "Red Dragon Dojo",
       master = ninja { name = "Kakashi",
                        age = 26 } }

When we test the service method we basically can take two approaches:

  • Writing a unit test for each property of a object graph
  • Asserting multiple properties in each test

Unit test per property

[Test]
public void FindDojo_WithKakashi_ShouldReturnDojoWithNameRedDragonDojo()
{
   // act
   var result = service.FindDojo("Kakashi");
   // assert
   Assert.AreEqual("Red Dragon Dojo", result.Name);
}

[Test]
public void FindDojo_WithKakashi_ShouldReturnDojoWith26YearOldOwner()
{
   // act
   var result = service.FindDojo("Kakashi");
   // assert
   Assert.AreEqual(26, result.Master.Age);
}

I usually went this approach when testing bigger object graphs, because it provides the most information when failing. On the other hand, it's a whole load of work to implement all these tests.

Multiple assertion per test

[Test]
public void FindDojo_WithKakashi_ShouldReturnRedDragonDojo()
{
   // act
   var result = service.FindDojo("Kakashi");

   // assert
   Assert.AreEqual("Red Dragon Dojo", result.Name);
   Assert.AreEqual(26, result.Master.Age);
}

With this approach it takes less time to write the unit test. However, when the test fails because Kakashi go one year older, all we get is the following message:

Expected: 26
Actual: 27

When having bigger object graphs, especially in integration test environments, the information provided by the test can save a huge amount of time. The second problem with this test: if the first assertion fails, the second one never gets executed.

The exas way

The same unit test written with Extended Assertions looks like this:

[Test]
public void FindDojo_WithKakashi_ShouldReturnRedDragonDojo()
{
   // act
   var result = service.FindDojo("Kakashi");

   // assert
   result.ExAssert(r => r.Member(x => x.Name)  .IsEqualTo("Red Dragon Dojo")
                         .Member(x => x.Master).Fulfills(n => n.Member(x => x.Name).IsEqualTo("Kakashi")
                                                               .Member(x => x.Age) .IsEqualTo(26)));
}

There is certainly more code to write in this test. Do we get some benefit out of that? Let's look at the exception message, if Kakashi got a year older:

Dojo: ( )Name   = "Red Dragon Dojo"          (expected: "Red Dragon Dojo")
      (X)Master = Ninja: ( )Name = "Kakashi" (expected: "Kakashi")
                         (X)Age  = 27        (expected: 26)

The error message provided by Extended Assertions shows us each checked value, nicely formated.