loading...

Build a TDD Restful WebAPI for a Blog using dotnet core

mrsimi profile image Mr. simi ・7 min read

Introduction

In this article we would be talking about implementing TDD (Test-Driven Development) in a WebAPI for a blog, Excited? But before we dive into all the coding, we would talk a little about TDD.

So what is Test-Driven Development?

I actually like the definition from Wikipedia, appears to give the whole picture in few words. According to whomever wrote that part, TDD is a software development process that relies on the repetition of a very short development cycle; requirements are turned into very specific test cases; then the software is improved to pass the new test only.

But honestly that definition up there is what TDD is about. Yeah, there is a lot of software jargon involved, which we will get to soon, but understanding this in plain English sets us on the write path.

What are the steps involved in TDD?

Red Green Refactor Cycle is the software jargon that sugarcoats the entire steps involved in TDD.

  1. RED: This is the first step, where you write the code to test your use case. Remember, you are starting a blank code file, so this test must fail. Do not be tempted to write anything to make the test pass, not even defining classes. This failure is what makes it know as RED.
  2. GREEN: This is the next step where you write the code to make your test pass. The rule at this point is to write enough code to pass only that test. Continue writing code until the test is passed, never leave a test red and write another one.
  3. REFACTOR: This is the step you make your code beautiful by refactoring. You make it cleaner by doing several things not limited to but include obeying the rules of your language, your design, your architecture etc.

Here is the summary, Write test for your use case which must fail the first time, then write enough production code to make it pass.

So let's code

Create a WebAPI project

I would be using Visual Studio Community 2017 in this tutorial, but feel free to use any IDE of choice that support dotnet core. Follow this steps, if you are like me:

  1. File > New Project > Select ASP.NET Core Web Application
  2. Rename to a name of your choosing, mine is "TddBlogDevto", then click Ok
  3. It should take you to the page where you select the template, just select API and click OK
  4. You should be up and running, run it to ensure everything is fine.

Setup for Testing

The kind of testing we would be doing in this tutorial is called unit testing, lamely; when you test units which could be described as functions/methods.

The testing is mostly done using some sort of framework to make the work easier. And in this case, we would be using the xunit framework. Here are the things to get it setup:

  1. Right click your solution > Add > New Project
  2. On the project panel Select xUnit Test Project(.NET Core) template
  3. Rename to something really meaningful and related to your projects which in my case is TddBlogDevto.Tests
  4. You should have a new project and a default class which we should change the name to something also meaningful. Meaningful naming is essential in all type of coding.

Writing our first test

As the title so depicts, we are writing an WebAPI for a blog. So it is quite obvious that the first thing we want anyone using our API to get is the list of posts, right?

There you have it, your first test case, writing a test for displaying the list of posts. Okay?

A bit jargon at this point. You know we said we are to display a list but how do we trick the class into believing we have a list without actually having one. The way to do this is called creating mock, sort of a fake value for a real class.

In this case, we are going to try to mock a list of post and we are going to do it using a nuget package called Moq. I know right, lots of frameworks and libraries just to write tests, but you know all programmers are lazy so we look for the way that makes us write the less code in clean ways.

Right Click your solution > Manage NuGet Packages > Browse > Search for "moq" > Install it

We now have a way to mock the classes. Yay!

Something before we move far,

Right Click your test project (BlogDevto.Tests) > Add > Reference > Select your production project (BlogDevto).

This helps to add reference to the production project.

Write this code inside the class inside the test project,

public class BlogService
    {
        private readonly BlogController _blogController;
        private Mock<List<Post>> _mockPostsList;


        public BlogService()
        {
            _mockPostsList = new Mock<List<Post>>();
            _blogController = new BlogController(_mockPostsList.Object);
        }

        [Fact]
        public void GetTest_ReturnsListofPosts()
        {
            //arrange
            var mockPosts = new List<Post> {
                new Post{Title = "Tdd One"},
                new Post{Title = "Tdd and Bdd"}
            };

            _mockPostsList.Object.AddRange(mockPosts);

            //act
            var result = _blogController.Get();

            //assert
            var model = Assert.IsAssignableFrom<ActionResult<List<Post>>>(result);
            //Assert.Equal(2, model.Value.Count);
        }

Let's explain the test code

private readonly BlogController _blogController;
private Mock<List<Post>> _mockPostsList;

The BlogController is from our production code. The controller is the entry point for our WebAPI, it is a class we wish to implement in our production code to expose our webAPI. The Mock is a mock class of a list of Post. We have List of Posts that we want to Mock so we use this code (we discussed mocking earlier).

public BlogService()
        {
            _mockPostsList = new Mock<List<Post>>();
            _blogController = new BlogController(_mockPostsList.Object);
        }

Here is the constructor (a method that has the same name with the class) where we assign the variables we declared previously. We are basically saying when this class is created assign these values to an instance of Mock>() and an instance of BlogController while passing in _mockPostsList.Object

The first seven lines of code we just discussed is just a way of Object oriented design thinking by injecting an object into the constructor. Please bear with me and do not stray away from the goal of this tutorial, TDD.

       [Fact]
        public void GetTest_ReturnsListofPosts()
        {
            //..
         }

This is the method that test if a list of post is return which should be obvious from the name. Name is very crucial in coding especially in testing; your method name should explain what the test does.

The [Fact] attribute that designs this class is from the library we are using for testing, xunit. It is a way of telling the compiler that this class method is test method.

The way we approach testing in dotnet and I think most language is the 3As; Arrange, Act Assert. I would explain as we go.

         //arrange
            var mockPosts = new List<Post> {
                new Post{Title = "Tdd One"},
                new Post{Title = "Tdd and Bdd"}
            };

            _mockPostsList.Object.AddRange(mockPosts);

This is the arrange part. We are arranging the data or the output that we need, in this case a list of post. The var mockPosts is just plain old csharp variable representing a list of Post. After the creation of mockPosts we added it to the List we created before the mockPostsList.

This is the essence of a mock. We have a class of Post and trying to create some fake/mock posts which we later add to a mock/fake list to stand as our reference.

//act
var result = _blogController.Get();

The Act part. Here we get the supposed implementation of the use case (i.e. a method that list all the post). We are proposing that the Blog Controller class would have a Get class.

//assert
var model = Assert.IsAssignableFrom<ActionResult<List<Post>>>(result);

The Assert part is the part were we check if the proposed result from act correlates with the reference.

In our case we are asserting that the result from act is in fact a List of Posts.

To run:

Open up the test Explorer: Test > Windows > Test Explorer

This would show all the methods inside the class.

Run the GetTest_ReturnsListofPosts test. Remember it must fail. If it doesn't you have failed.

Also remember that compiler error is also a failure

If the test has failed then we begin to think of how to pass it.

  • We need a class of Post since we are to return of list of Post. Thus go into the production project (TddBlogDevto) and add a class file and name it Post. Put the following code inside.
public class Post
{ 
   public Guid Id { get; set; }
   public string Title { get; set; }
   public string Content { get; set; }
}

This model just contains the definition of the Post; a post must contain an Id, a Title and a Content. Plain Old Clr Object.

  • Create a Controller title BlogController. Right Click your production Project > Add > Controller > Select API Controller Empty .

Write the following code inside it:

 private readonly List<Post> _posts;
public BlogController(List<Post> posts)
{
   _posts = posts;
}
public ActionResult<List<Post>> Get()
{
   return _posts.ToList();
}

This code is the actual implementation that gives the list of Post. The Get Method returns the previous defined list _posts.

This method was the one we were calling in act part of the test we previously wrote, Got it?

  • At this point we should be set, but if there are any red underlines in your code, check to see if the reference is missing; mostly due to the file being inside a folder.

  • If no red underlines. Run the test again. This time, if all is done right, we should pass.

Conclusion

If all things work well, we have successfully implemented a WebAPI using dotnet core following the TDD principle. And always remember these rules of TDD; write implementation of the use cases (test), make sure it fails, then write enough production code to pass only that test, nothing more. You should go on to implement the other test for the remaining use cases that a blog might need.

I hope I have being help to you. Here is the link to the github repo where I actually implemented a lot of test. https://github.com/mrsimi/BlogAPIusingTDD

Happy coding!

Discussion

pic
Editor guide