In this post we see how to do unit testing in .NET Core with xUnit.
xUnit is a popular framework, with a lot of features and helpers to develop quickly our unit testings and implement them with a clean syntax; it’s very efficient and the result is that the tests execution is very fast.
In the previous post we implemented a basic class with an in-memory DbContext, that we’ll use in the unit test.
The service
We can suppose that our sut is a service, like CategoryService.
The service has some methods to retrieve the category from the database with Entity Framework.
The service look like this:
public class CategoryService { readonly BlogContextFactory _contextFactory; public CategoryService(BlogContextFactory contextFactory) { _contextFactory = contextFactory; } public IEnumerable<Category> GetCategories() { using (var db = _contextFactory.GetNewDbContext()) { return db.Categories.OrderBy(c => c.Name).ToList(); } } public async Task<Category> AddCategory(Category category) { using (var db = _contextFactory.GetNewDbContext()) { category.Id = Guid.NewGuid(); await db.Categories.AddAsync(category); await db.SaveChangesAsync(); return category; } } public async Task UpdateCategory(Category category) { using (var db = _contextFactory.GetNewDbContext()) { db.Categories.Update(category); await db.SaveChangesAsync(); } } public async Task DeleteCategory(Category category) { using (var db = _contextFactory.GetNewDbContext()) { db.Categories.Remove(category); await db.SaveChangesAsync(); } } }
Unit Test class
Now we can implement the Unit Test class; we can use the base class DatabaseFixture and pass the context factory configured with an in-memory DbContext to the service:
public class CategoryServiceTests : DatabaseFixture { readonly CategoryService _categoryService; public CategoryServiceTests() : base("CategoryContext") { _categoryService = new CategoryService(ContextFactory); } [Fact] public void should_return_categories_list() { var categories = _categoryService.GetCategories(); categories.Should().NotBeNullOrEmpty(); categories.Count().Should().BeGreaterThan(0); } [Fact] public async Task should_add_new_category() { var category = new Category() { Id = new Guid("{1225FE5B-9C46-4BA3-9233-9337DDC5F478}"), Name = "Test Category" }; category = await _categoryService.AddCategory(category); using (var db = ContextFactory.GetNewDbContext()) { var newCategory = await db.FindAsync<Category>(category.Id); newCategory.Should().NotBeNull(); } } [Fact] public async Task should_edit_category() { using (var db = ContextFactory.GetNewDbContext()) { var category = await db.FindAsync<Category>(new Guid("{BE7EB1E1-FB67-4FE1-A96E-4721D37AFE29}")); category.Name = "category modified"; await _categoryService.UpdateCategory(category); category = await db.FindAsync<Category>(new Guid("{BE7EB1E1-FB67-4FE1-A96E-4721D37AFE29}")); category.Name.ShouldBeEquivalentTo("category modified"); } } [Fact] public async Task should_delete_category() { var category = new Category() { Id = new Guid("{5D134CF2-EF37-4663-B3D2-64F2E3DBF3BE}"), Name = "Category1" }; await _categoryService.DeleteCategory(category); using (var db = ContextFactory.GetNewDbContext()) { category = await db.FindAsync<Category>(new Guid("{5D134CF2-EF37-4663-B3D2-64F2E3DBF3BE}")); category.Should().BeNull(); } } }
The Fact attribute is the xUnit attribute used for the test methods.
As discussed above the ContextFactory is configured to returns an instance in-memory of the DbContext.
Now we can run the unit test by opening a command console, going to the UnitTest project folder and running the command:
dotnet test
The command will run the tests and will show us the results.
You can find the source code here.
Leave a Reply