Testing .Net Core Code with XUnit- Asserting

.Net Core Dec 01, 2019

This is the first part of my posts about using Testing .Net Core Code with XUnit and its features for testing code, these posts series cover all parts of xunit in detail.

XUnit is a testing framework that allows us to write tests on our production code. suppose we have some C# production code which is in our production project and we have some test classes in our TestProject for testing our production code. the test project has a reference to our production project for testing classes in our production project and also we install XUnit library on our TestProject with Nuget, and now we can write XUnit based test class in our test project.

once we’ve written our tests we need some tools to run them and for this purpose, we use a Test Runner. test runner can read our test code and our test framework and find tests in our test project and execute our test and give us the feedback and result of the tests. there are some test runners such as visual studio test explorer, .Net Core CLI for run Tests and Resharper test runner.

Create Test Project with XUnit

For this post, I create a sample file with the name of XUnitSamples, which is a console application project using .Net Core 2.2. you can find these post series in this Github Repository.

Now to Add an XUnit Project for testing our sample, in visual studio we can right-click on the solution and Add->New Project and search XUnit in the search bar and choose XUnit Test Project(.Net Core) and let’s call it XUnitSamples.Tests and add this project to our solution.

XUnit in .Net Core

If we see our project references, we can see it automatically added Nuget packages for XUnit to our projects that these packages: xunit , xunit.runner.visualstudio as you can see in the below csproj file. xunit is xunit core package and  xunit.runner.visualstudio the package allows to visual studio test explorer to be able to discover tests and execute our tests.

XUnit in .Net Core

Our test project also needs to access our XunitSamples project and its classes so we can right-click on our test project and add a reference to our sample project.

we also can use .Net CLI to create a XUnit Test project for this purpose in our root folder our application we can use dotnet new xunit -n XUnitSamples.Tests -o XUnitSamples.Tests command to create XUnit Test project, you can see help for xunit with this command dotnet new xunit -h.

now we need our test project has a reference to our sample project so we use dotnet add reference ../XUnitSamples/XUnitSamples.csproj  command to add a reference to the sample project. we can also use the .Net CLI to add our test project to our solution so for doing this we first go to root project that our solution file exist there and use dotnet sln add XUnitSamples.Tests\XUnitSamples.Tests.csproj command to add our test project to the solution.

Start Using XUnit

For start a test with xunit we create a class with the name of MathTests for testing our Math class in our production code.

Our production Math class is this:

Here we use [Fact] attribute from XUnit to discover this method as a test method by the test runner. we named this method to Add_WhenCalled_ReturnSumOfInputs that “Add” is the name of the method we calling on SUT (method on the test) so method on the test is “Add” and “WhenCalled” is what scenario we test here, in this code, we use this term for our purpose our scenario and last section “ReturnSumOfInputs” says add method when called, it should “ReturnSumOfInputs” actually it is our expected behavior. now we can run this test with visual studio test explorer and it should pass.

XUnit in .Net Core

Assert in XUnit

Call a utility method to evaluate whether an expected outcome has been achieved.

An assertion is a boolean expression at a specific point in a program which will be true unless there is a bug in the program. A test assertion defined as an expression, which encapsulates some testable logic specified about a target under test.

Assert is a class useful in determining Pass or Fail status of a test case, Xunit provides a class named Assert, which provides a bunch of assertion methods useful in writing test cases and to detect test failure.

There are various types of assertions like Strings Assert, Boolean Asset, Null Assert, Numeric Assert, Identical Assert.

Xunit also supports a number of ways for assert on collections, Xunit supports assert On Raised Events and supports Object Types assert.

Each Test should have at least one assert and it can have more than one asserts but our asserts must relative to behavior or our test case goal that we testing.

Asserting Boolean

In xunit there is an assert to evaluate boolean value on the system on the test and compare it with the expected value.

In this sample, we call the IsOdd method on SUT and check our result return to be true with passing the result to the True method on Assert class. if the result is the same as our expected value the test will pass otherwise it will fail.

Asserting Strings

For assert string values in xunit we can use the Equal method on Assert class to compare our result on SUT and our expected value.

In this example, we call GetTimeOfDay method on our SUT and we passed 7 as TimeSpan value to our method then compare the result with our Expected value that in this case is “Morning”, If the result will be the same test will pass otherwise it will fail.in xunit we have also some other assert methods for evaluating results with expected value such as Assert.StartsWith(string expectedStartWith,string actualString) and Assert.EndsWith(string expectEdendWith,string actualString). For example, in the above example, we can write Assert.StartsWith("M",result) to check our test result to Start with “M” character otherwise, it will fail.

If we want to compare two string with ignoring case options we can use Assert.Equal(string expectedString, string actualString,bool ignoreCase) , for example, in the above example we can write this code Assert.Equal(“morning”, result, true) method for check our result is equal to expected value without case sensitivity and our test will pass because case sensitivity is not important.

xunit also supports Assert.Contains(string expectedSubstring,string actualString) method that evaluates our result contains expected substring such as Assert.Contains(“orn”, result).

Numeric Assert

We can use xunit to assert and evaluate numeric values, for this case we can use Assert.Equal<int>(int expectedNumber,int actualNumber) method for example in bellow test we use the Equal method this time for check and evaluate numeric values and in this sample we check our expected value are equal to our result on the system under the test and our test should pass.

We also have a compliment of equal in xunit that is Assert.NotEqual<int>(int expectedNumber,int actualNumber) and it asserts our result should not equal with the expected value.

To test our result to be in a specific expected range we have two options in xunit so in the first option we can use the True method for this case such as  Assert.True(result <= 10 && result >= 1) for second option we can use Assert.InRange<int>(int actualValue ,int lower-Bound, int higher-Bound) generic method and check our system under the test result with a range of values that lower-bound is minimum expected value in our range and higher-Bound is upper value in our expected range now if our result placed in this expected range our test will pass otherwise it will fail.

The second approach is better because if the test fails, it gives more detail and helpful error message against the True method.

Asserting Null

There are two methods for working with null in xunit Null and NotNull. with the Assert.Null(object actualObject) method, we can check whether our result object on SUT is null or actually it has a null reference the test will pass otherwise it will fail. we have also a compliment method for assert null value, Assert.NotNull(object actualObject) method verifies that our object is not null reference. we create two samples for check null and not null value in our test.

Asserting Collection

We can use the different approaches for asserting collection in Xunit that we mention some of them here. for example, we have a method let’s call it GetOddNumbers and takes a limit value input as a parameter and returns odd numbers from zero up to this limit value. I write some tests for this method here. our test scenario is LimitValueIsGreaterThanZero and our expected behavior is ReturnsOddNumberUpToLimit.

One of most general way to write assertion for collection is checking our collection is not empty with this Assert.NotEmpty(IEnumerable actualCollection) method that verifies a collection is not empty, it is very general and we don’t care about specific values in our collection but we just wanna make sure there is something in our collection so for this case we can use this method. a more specific way of testing a collection is to test the number of items in this collection so we can use this Assert.Equal<int>(3 , result.Count()) method, it is a little more specific.

we can also write another general assertion for this collection using Assert.Contains<int>(int expected, IEnumerable<int> actualCollection) method we can verify our test collection contain specific values for example Assert.Contains(1, result) in our example and we can also use Assert.DoesNotContain<int>(int expected, IEnumerable<int> resultCollection) method to verifying our collection doesn’t contain a specific value in our test collection.

we can also use Contain method with a predicate as a filter  Assert.Contains<int>(IEnumerable<int> actualCollection, Predicate<int> filter)  in our example, we check our test collection contains a specific value with a predicate with this code Assert.Contains<int>(result, item => item == 1).

there is a way for a cleaner and easier assertion of collection for checking for existing some specific values in the collection or our total collection is as expected with this Assert.Equal<int>(IEnumerable<int> expectedCollection, IEnumerable<int> actualCollection) and an example of this in our code is Assert.Equal<int>(new[] { 1, 3, 5 }, result).

if we want to assert against each item in our collection we could use a loop and assert each item separately but we can use an easier way with Assert.All<int>(IEnumerable<int> collection ,Action<int> action) method loop through  all of our items in this example and execute our action in this example  Assert.All(result, item => Assert.True(item > 0)) we check all of the items are greater than of zero with using the Assert.True() method.

Object Type Asserting

If we have Inheritance hierarchies in our application some times we need to check some hierarchy level for a specific type and some times we want to check the exact object type, for these purposes xunit provides two assertion methods, Assert.IsType<T>(object actualObject) method that evaluates our object under the test is exactly the same as a given type specified in the generic type of IsType method, not a derived type we also have a compliment of this method Assert.IsNotType<T>(object actualObject).

also, we have a Assert.IsAssignableFrom<T>(object actualObject) the method that verifies our object under the test is exactly the same as a given type or one of its derivatives of the type that specified in the generic type of IsAssignableFrom method.

I show you the use of these assertions in this sample for PersonController class:

Our tests for this controller:

In this test class in this method GetPerson_IdIsNotZero_ReturnOk we checked our actual object is exactly the same as the given type OkObjectResult with this code Assert.IsType<OkObjectResult>(actual.Result) and store the result of our assert in a variable for use in the future asserts. also, we verify our actual object is exactly the same type of PersonModel or one of its derivatives with this code Assert.IsAssignableFrom<PersonModel>(okObjectResultAssert?.Value) because of ObjectResult.Value is of type object and object is one of the PersonModel derivatives.

Reference Equality Assertion

We can also check two object references are equal that means two objects point to the same reference in the memory, xunit has two methods for this purpose, Assert.NotSame(object expectedObject, actualObject) and Assert.Same(object expectedObject, actualObject). for Assert.Same it checks objects have the same reference and Assert.NotSame method checks our objects don’t have the same reference.


In the above example, we write two tests to check reference equality, the first example checks our object to have the same reference and the second one checks our objects don’t have the same reference.

Exception Asserting

If during a test execution thrown an error our test will fail, but for more confidence in our code, we can check that our code throws the exceptions at correct times for this purpose xunit provides an assertion method Assert.Throws<T>(Action testCode) or Assert.Throws<T>(Func<object> testCode) that will catch the exception and assert the type of our exception.

the generic type of T in this method is the exact not derived expected  exceptions type to be thrown, In the case where you want to also allow derived exceptions, the Assert.ThrowsAny<T>(Action testCode) method can be used and the method parameter takes an Action or Func delegate that should cause this exception to be thrown below code is a sample of an exception asserting:

In this sample, if we pass zero as an input parameter for the second argument we expect our system under test method throw an DividByZeroException , so in this situation, our test should pass and if an DividByZeroException is not thrown when our system under test method is called the test will fail. also, The thrown exception can store in a variable and use in subsequent assertions.

Rasing Events Asserting

One of the other xunit features is asserting raised events, with this feature we can check our events raised or not. here in our Person class, we have an event IsActiveChanged that will raise whenever our Person active state changes.

in bellow sample, we want to test our person domain class so we create a test for IsActive property that we named it, in our test we prepare our test with initializing our SUT (person domain class), now for verifying our domain class raise IsActiveChanged event correctly before acting we should subscribe to the event, so when IsActive property raises the event we will be notified.

xunit has a method to do this Assert.Raises<TEventArg>(Action<EventHandler<TEventArg>> codeToattach, Action<EventHandler<TEventArg>> codeTodettach, Action testCode) which in this method T is our expected event args when event raises and we need to provide some arguments, the first argument is an action which attaches to the event, here in our sample we use a lambda expression xunitHandler => sut.ActiveStateChanged += xunitHandler for attaching xunit handler to our event.

the second argument is code to detach from the xunit event handler for this we use this lambda expression xunitHandler => sut.ActiveStateChanged -= xunitHandler and the last parameter is the action that we use to raise our event, actually, use for calling our system on the test scenario. in our example with this lambda expression, () => sut.IsActive = true we call our IsActive property and set it with a value, now if  IsActive property is set and our ActiveStateChanged event has raised this test will pass otherwise if our event does not raise our event the test will fail.

This was the first part of using XUnit in .Net Core Series, in the next post we’ll talk about other features of xunit.

Tags

Mehdi Hadeli

I’m a software engineer with +10 years of experience in developing and designing distributed applications built on top of cutting-edge technologies with interest in Microservices, DDD.

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.