Mocks in the test environment (Part 3)

In the second part, we saw how a mock framework (in this case Moq) can be used to modify an application in such a way that certain interfaces are mocked for testing and thus cannot deliver errors.

In this part we will create a self-programmed mock application and will access it with our hero database. For this we use “Docker for Windows”, which can be used since Windows 10. Before Windows 10 you had to use Hyper-V, for example to simulate a Linux machine on which you could run containers via docker. With the latest operating system from Microsoft, this procedure is also possible on Windows. You can download and install the latest version at Docs.docker.com. The downloaded installer prepares the system for Docker.

With Docker we start our hero database – as well as the APImock application that we will be building shortly. With the Postman we will then make a POST request that runs in the APImock via the hero database.

Representation of the application
Figure 1: Representation of the application

Visual Studio has an extension that enables support of Docker. When creating a new project we can check the box in the template window to combine the project with Docker for Windows. We also use the Web API template to avoid having to create a completely new project.

Visual Studio - creating API with docker
Figure 2: Creating a web API in Visual Studio

When the project is loaded, an image is directly created in Docker. Each time the project is built, the image is updated in Docker.

We can now run the Docker commands at the same time in Windows PowerShell to get our current images.

PS C:\Users\neco.giedrojc> docker images
REPOSITORY                    TAG            IMAGE ID            CREATED             SIZE
apimock                    	dev             c64f4ccd31cd        2 days ago          1.13GB
herodatabase                   dev             5feaebecd325        2 days ago          13.3GB

The images can be uploaded to a repository similar to GitHub for version control and access from multiple workstations. To do this, modify the image tag to match the repository name and upload it using the push command.

PS C:\Users\neco.giedrojc> docker  tag   5feaebecd325  tester_user/herodatabase
PS C:\Users\neco.giedrojc> docker  push  tester_user/herodatabase
The push refers to repository [docker.io/tester_user/herodatabase]
6d8d18d60d45: Pushed
89d570a16fde: Pushed
c18c4a07904a: Pushed
latest: digest: sha256:d37cf6481f52a72e1b760f98824ceefc758a7ab2924759d6881db9ef444f9db2 size: 1565
PS C:\Users\neco.giedrojc>

Since the Web API template was used, the four standard REST commands (GET, POST, DELETE, PUT) are already pre-generated in the controller class. We delete all functions except POST, because this is supposed to be a “trivial function” for the mock.

[Route("api/items")]
[HttpPost]
public String PostMock([FromBody]String itemHero)
{
    String algo = "sword";
    /**
    * here should be a function which calls an algorithm.
    * but this is just a mock so one hardcoded line is enough
    */

    return algo;
}

So now we have an application that has only one function and does not do anything else. The basic idea for this interface is that the database API sends the hero name to this application to get the item configuration for that hero. This means that the PostMock() function is executed on a POST request and the supplied hero name would use the algorithm for the request. However, here instead of an algorithm a fixed string is used, which always returns the same answer to each request. This ensures that no errors will come from the new application. This also ensures that this interface works as desired.


[Route("api/hero/Mockitems")]
[HttpPost]
public async System.Threading.Tasks.Task<String> MockCallAsync([FromBody]String heroname)
{
    using (var client = new Webclient())
    {
        var values = new NameValueCollection();
        values["name"]= heroname;

        var response = client.UploadeValues("http://localhost:7266/api/items", values)

        var responseString = Encoding.Default.GetString(response);

        return reponseString;
    }
}

In the hero database API a POST function has been implemented which forwards the request for the hero name to the APImock. For this purpose the WebClient class is used, which is filled with a string (hero name). This is then forwarded via the function of the class UploadValues().

Both applications are now ready and can be started in Visual Studio via the docker button. As soon as both applications are started, you can view the currently running containers via the PowerShell. With the docker command “docker ps” we also get to know the port the containers are running on.


PS C:\WINDOWS\system32> docker ps
CONTAINER ID        IMAGE                                 CREATED                STATUS                     PORT
2aa75e039429        herodatabase:dev        7 minutes ago       Up 6 minutes        0.0.0.0:23337
f3ae2ca8c6d0         apimock:dev                         10 minutes ago      Up 10 minutes      0.0.0.0:7266 

If we now make a request with the postman to the route “api/Heroes/MockItems” of the Heroes Database API, it is forwarded to the APImock and we see the answer for the hero “Maria”.

Screenshot Interface test with Postman
Figure 8: Interface test with Postman

The unmocked application would in this case list the appropriate equipment for the hero “Maria”. However, since this is a mock, the return string “sword” matches the fixed variable we set.

So now you can test all functions that use the interface to the APImock without expecting errors from the APImock.

Now we have seen three different ways of using mocks:

  1. The framework Moq, which is used to create Mock objects within the application
  2. API tools (Postman), which are a kind of mock for the frontend
  3. A self-written application that serves as a mock

I hope I could give you a little insight into the world of mocks.

Mocks in the test environment (Part 2)

In the first part the basics of the mock and the example project were presented. In the second part we build a mock that interactively tests our Rest-Service application.

Now the question comes up: “Why should I use a mock in this example?” After all, it’s a simple, straightforward application. However, we must remember that we want to test the standard functionality of the API. When we execute a GET or POST command, the rest of the service takes the complete path to the database to access the data already stored. This is where the mock comes into play. The access to the database is simulated by the mock. This ensures that if an error is found, it has nothing to do with the access to the database, but with the area in which we performed the test. This would be an example of the application area. Another would be the access from outside to the API. Normally such an API would have a frontend for entering the information. However, since we know the paths into which the data is fed, we can use an API tool that simulates the frontend and sends specific data to the API.

In this part I will talk about the mock framework “Moq” and the API test tool “Postman”.

Moq is a small and simple mock framework for .Net or C#. There are several frameworks (NSubstitute, Rhino Mocks, etc …) but they are usually quite complicated to use. Moq stands out in the sense that it uses a simple syntax and is perfectly adequate for most applications. The Moq framework package can be easily downloaded from Visual Studio with the nuget tool and directly included in the source code.

using System.Net.Http;
using Moq;
using NUnit.Framework;

Here the simple structure of a unit test. We create a new hero list, which gets its data from the database. With this information we can create the service which is consumed by the API. We call up the fourth hero we have stored. In this case it would be “Maria”.

[Test]
  public void TestMethodwithoutMoq()
{
    //Arrange (Create)
   Herolist h_list = new Herolist();
   var heroAPI = new HeroService(h_list);
   string shouldBe = „Maria“;
   //Act (Test)
   var result = heroAPI.GetHeroName(4);
   //Assert (Verify)
   Assert.That(result,Is.EqualTo(shouldBe),“Is Not as Aspected“);
   }

[Route(„api/hero/{number}“)]
[HttpGet]
public string GetHeroName(int number)
{
   Hero hero = heroAPI.GetHero(number)
   Return hero.name;
}

Now we take the already existing structure and replace the hero list with a mock. This way we no longer use the data stored in the database and have separated the application from the database for the time being. This setup guarantees that no errors from the database connection will interfere with the test.

[Test]
public void TestMethodwithMoq()
{
    Hero mockHero = new Hero()
{
    name = „Detlef“,
    class = „Wizard“,
    age = 40,
    level = 14
};
//Arrange (Create)
var moqHerolist = new Mock();
moqHerolist.Setup(x => x.GetHero(It.IsAny()))
    .Returns(() => mockHero);

var heroapi_mock = new HeldenAPI(moqHerolist.Object);
var shouldBe = „Detlef“;
//Act (Test)
var result = heroapi_mock.GetHeroName(It.IsAny());
//Assert (Verify)
Assert.That(result, Is.EqualTo(shouldBe), „Is Not as Aspectet“);
}

If the Moq framework is integrated, you can use the class “Mock”. When using the class, you specify which class should be simulated. The next step is to configure the mock with the setup() function. We specify that no matter which hero is asked for (It.IsAny), the mockHero (Detlef) will always be output. If we would not configure the mock, it would take a default value as integer when calling the GetHeroName() function. This is usually “0”. But since no data is fetched from the database, it would return an error.

The Moq framework can be used to test the functionality the API calls within your application. However, when calling the API directly, it reaches its limits. This is where the API tool “Postman” comes into play.

“Postman” can be installed as a separate application or used as a chrome plugin. It is equipped with most REST commands (GET, POST, PUT, etc…) and has an easy to use interface. It is possible to write test cases that run during the REST commands and work with the sent or received data. So, we build a mock with it, which simulates the frontend.

You can create “Collections” to store the REST commands we used in the last part. With the POST command we stored the heroine Maria via the API. Now we added a test case which checks the response text we got back from the API. In a positive case we get back that the desired hero has been added. In a negative case we would get another message and the Test-case would return Failed.

We also add the query for the last added hero to our “Collection”. You can add many more queries with your own test cases to the “Collection”, but for our example these two are sufficient. Now it is possible to start the complete “Collection”. The “Postman” will then call all REST commands one after the other and go through their stored Test Cases. So, we get such a result in the end:

We can see now that the access from outside, to the API works.

With these examples we see that with the Moq framework the application behind the API can be easily tested. The “Postman” on the other hand makes it easier to test the API from the Internet.

Überblick Postman und Moq Framework

In the next part we will continue to deal with this topic. We will build a small test environment in Docker where the Rest service will be built with the database, and a self-written mock application will continuously try to access the Rest API. This variant could also be used as a load test later on.

This was Mocks in the test environment. An here you’ll find part 3.