/rest-mock-core

A simple HTTP server for using as a mock in test projects which test dotnet based projects.

Primary LanguageC#MIT LicenseMIT

NuGet Badge Build Status Coverage Status codecov

rest-mock-core

A simple http server for using in test projects which test .net core based projects.

Problem

When I started to write some tests for a dotnet core app, I realized that many libraries do not work on that platform. One of my problems was to find an appropriate HTTP Server Mocking library. So, I created this project.

Install

dotnet add package rest-mock-core

Usage

You can create and run a mock server as below. Default url is http://localhost:5000 The port can be changed in the constructor:

using HttpServer mockServer = new HttpServer(5001);
mockServer.Run();

Then you can use any http client sending request to it.

HttpClient httpClient = new HttpClient(5001);
var response = await httpClient.GetAsync("http://localhost:5001/");
  • If you call the root of server, it will return "It Works!" with a OK status code (200). Of course it can be overrided by adding a responose for the root url.

  • You can use server.Config to manage requests, then server will return configured responses to your requests :

mockServer.Config.Get("/api/product/").Send("It Really Works!");
  • If you call a address which is not configured, you will receive "Page not found!" with status code (404).

Assert

You can mark each RouteItem as Verifiable and on the assert step all can be verified at once:

// Arrange
using HttpServer mockServer = new HttpServer(5001);
var users = new[]
{
    new User { id = 1, username = "user1" },
    new User { id = 2, username = "user2" },
    new User { id = 3, username = "user3" },
};
var _usersJson = JsonSerializer.Serialize(_users);
mockServer.Config.Get("/api/users").Send(_usersJson).Verifiable();
mockServer.Config.Get("/api/users2").Send(_usersJson).Verifiable();
mockServer.Run();

var apiClient = new ApiClient("http://localhost:5001/api/users");
var apiClient2 = new ApiClient("http://localhost:5001/api/users2");

// Act
_ = await apiClient.GetUsernames();
_ = await apiClient2.GetUsernames();

// Assert
mockServer.Config.VerifyAll();

Also it is possible to verify each route item in different ways:

  • Simply verify:
//Arrange
...
var routeItem = mockServer.Config.Get("/api/users")
                                 .Send(_usersJson)
                                 .Verifiable();
mockServer.Run();

var apiClient = new ApiClient("http://localhost:5001/api/users");

// Act
_ = await apiClient.GetUsernames();

// Assert
routeItem.Verify();
  • Verify by an action:
//Arrange
...

// Act
_ = await apiClient.GetUsernames();
_ = await apiClient.GetUsernames();
_ = await apiClient.GetUsernames();

// Assert
routeItem.Verify(x => x == 3);
  • Verify using Moq Times:
//Arrange
...
// Act
_ = await apiClient.GetUsernames();
_ = await apiClient.GetUsernames();
_ = await apiClient.GetUsernames();

// Assert
routeItem.Verify(x => Times.AtLeast(2).Validate(x));

More

There are some options to manage the requests easier:

mockServer.Config.Get("/api/v1/product/123").Send("It Really Works!");
mockServer.Config.Post("/api/v2/store/a123b").Send("Failed", 503);
mockServer.Config.Delete("/contact/y7eEty9").Send("Done", HttpStatusCode.OK);
mockServer.Config.Put("/branche/northwest1254").Send("updated", 200);
mockServer.Config.Get("/messages/123").Send(context =>
            {
                context.Response.StatusCode = 200;
                string response = "<h1>Your new message<h1>";
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(response);
                buffer = System.Text.Encoding.UTF8.GetBytes(response);
                context.Response.Body.WriteAsync(buffer, 0, buffer.Length);
            });

Also, it is possible to use other types of 'http method' by using 'Request':

mockServer.Config.Request("PATCH", "/api/v2.3/products/3234")
                 .Send("We don't use PATCH here.", HttpStatusCode.MethodNotAllowed);

Lastly, headers can be added to the request:

Dictionary<string, string> headers = new(){{"user-agent", "IE6"}};
mockServer.Config.Request("PATCH", "/api/v2.3/products/3234", headers)
                 .Send("C'mon man! Really IE6?", HttpStatusCode.MethodNotAllowed);
  • You can use server.Config either before or after server.Run()
  • Don't forget to use using when instantiate HttpServer, otherwise server may not be disposed.

For more details please check Test project.

Acknowledgements

JetBrains kindly provides this project with a free open-source licence for their Resharper and Rider.

  • Resharper makes Visual Studio a much better IDE
  • Rider is fast & powerful cross platform .NET IDE

image