Asp.Net Core 2.0 Web Api Unit Testing

There exist many kind of tests: unit tests, integration tests, acceptance test, UI tests.
The goal of this tutorial is to show how to write unit tests that gives us  a better return on test investment. 

UNIT TEST: Unit testing test behavior of a class and drive its implementation, run in memory and mocks the Data Access Layer 

INTEGRATION TEST: test the entire system and focus on interactions between many classes, uses the real database and test the Data Access Layer and its value is to catch regressions 

SUBCUTANEOUS TEST:  test that operates just under the UI of an application. This is particularly valuable when doing functional testing of an application: when you want to test end-to-end behavior, but it’s difficult to test through the UI itself. Martin Fowler ( https://martinfowler.com/bliki/SubcutaneousTest.html) 

UI TEST: tests the user interface and verifies that the entire application is working properly 

Let’s consider the following testing pyramid 

TestingPyramid

The further we go to the top of the pyramid 

  • tests are fewer 
  • the tests are less stable
  • More complex 
  • Narrower scope 
  • Slower in execution time 

The further we go down the pyramid 

  • Less we have tests 
  • the tests are more stable,
  • Less complex 
  • Broader reach 
  • Faster in execution times 

Let us consider the following project dependencies :

For the goal of this tutorial, I will not write unit test of all my projects even if all projects must be unit tested but I will proceed as follow: 

  • Unit Test my business Projet: LogCorner.BlogPost.Business 
  • Integration Test of my WebAPI project: LogCorner.BlogPost.Api 
  • UI Test of my web application : LogCorner.BlogPost.Mvc 

Lets talk about Unit Testing TDD or BDD? 

BDD approach: in absolute terms, TDD plus natural language  expression using Gherkin. 

Using TDD approach, we must write the tests first using the red-green-refactor cycle. 

RED: Write the test first, it will fail 

GREEN: Write tested code as simple as possible to make it pass 

REFACTOR:  Refactor your code; your test may fail, so make it pass again 

But if you have already a production code, how to test it? 

Given the previous class, I would like to unit test my UpdateAsync method. 

To update a blog post, I must verify this: 

  • You must provide a non nullable blog post objet and your email 
  • The blog post , you want to update must exist on database 
  • You must be owner of the blog post you want to update 
  • The system must replace blog post description and url, with the values provider by the user 
  • The system must call GetRepository<Blog>().Update(old) to perform update 
  • The system must call SaveAsync() to save updated blog post 

TEST 1 : To update a blog post, the user must provide a non nullable blog post objet and his email adress

Here, I verify, if the user provide a null blog or an empty or null email address then an ArgumentNullException is thrown

TEST2:  The blog post , you want to update must exist on database 

I want to test the following:  

I call GetAsync to retrieve the blog post by Id and I verify if the result is null or not 

As you can see  GetAsync make a call to _unitOfWork.GetRepository<Blog>().GetByIdAsync(blogId); 

So, I must mock the call of  GetByIdAsync(blogId); to return an existing blogpost. 

Here I mock IUnitOfWorkCore<LogcornerBlogpostContext> because my blogService need it and I don’t want to use the real implementation of my repository. 

Do not mock unitOfWork, means I’m doing integration testing but not unit testing. 

Let’s go ahead and write the test 

I verify, if the blog does not exist in database,  then an Exception is thrown

TEST 3 : To update a blog post , you must be owner of that blog post : you cannot update a blog post of someone else 

So, I want to test the following:  

I test if the owner field of the blog I want to update is different from the current user email, if so the system throws an exception. 

Let’s go ahead and test it 

TEST4: To update a blog post, you must set the url and description of the blog post you want to update with new values of url and description 

In this test I would like to verify the following 

old.Url = blog.Url; 

old.Description = blog.Description; 

I use a Verify call to check if the url and the description of the old blog are updated with new values

TEST5 : When the owner of a given blog try to uptade it , then the blog must be updated 

Test if SaveAsync is called

Regards

Gora LEYE

I'm a microsoft most valuable professional (MVP) .NET Architect and Technical Expert skills located in Paris (FRANCE). The purpose of this blog is mainly to post general .NET tips and tricks, www.masterconduite.com Gora LEYE