xUnit has different mechanisms to share test context and dependencies. Not only it allows us to share different dependencies between tests, but also between multiple test classes. We can also choose to get a fresh set of data every time for our test. So in this post, I’m going to go though those mechanism with some examples. Also I previously wrote about using
IClassFixture specifically, it might be beneficial to read this post first.
Test Cleanup Code Using Constructor and Dispose
One of the most important things to understand about how xUnit run tests, is that it we create a new instance of the test class per test. That means every time one of our tests in the same class needs to run, a new instance of that class is created. So if we put something in our constructor in the hope of sharing it between all of our tests in the class it’s not going to happen. Because as I said we receive a new instance every time.
That can be counter intuitive to some people. But the good part is that for our clean up code, we don’t have to rely on attributes such as set up and tear down like NUnit for example. We can do all of those things using the familiar C# constructs such as constructors etc. So the valid usage for the constructor could be sharing setup/cleanup code for all of our tests. Let’s look at an example.
In the code above, we share the code for our setup and cleanup of our test, and we’re going to receive a new instance for
InMemoryDbContext. In the next section we’ll see how to share
InMemoryDbContext between all tests in the same class.
Using IClassFixture to Share Context In One Test Class
There are situations when we want to share the instances of objects in our setup and cleanup. For example, maybe our dependencies are expensive to create and we don’t want it to be created once per test. So we need to somehow share the instance between all of our tests, we can do that using the
The first step we need to take is to create a class fixture that contains the dependency we need. Then we can use this class fixture like so.
Now we can access the db context through the property that we defined in our class fixture. We can create as many fixture as we need for a test class. But the important thing to note is that we are not in control of the order of creation of these fixtures.
Using ICollectionFixture to Share Context in Multiple Test Classes
In previous section we saw how to share a dependency between tests in the same class. In this section we see how we can share it between different test classes. The fist step is to create a fixture that we want to share between different classes. We already have done that by creating the
SharedInMemoryDbContextTests fixture. Then we need to create a
CollectionDefinition, this attribute helps us to categorize all of the tests classes under the same collection. If you want to know more about the concept of test collection, please refer to my previous post.
We can create our collection fixture as you can see in the code above. The next step is to apply this collection to our test classes. We can do that by using the
Collection attribute and using the collection name that we chose which in this case was “Context collection”.
xUnit treats collection fixtures the same way as it does class fixtures, except that the lifetime of a collection fixture object is longer. It is created before any tests are run in our test classes in the collection, and will not be cleaned up until all test classes in the collection have finished running.
In this post we saw how we can share test context using
ICollectionFixture. We also saw how we can use the constructor and dispose to setup and clean up resources for our tests. The samples used in this post can be found in this repository.