Skip to content

Mocking-Services

Feature Description

It is possible to mock a service described by a Service Contract interface via AspNet Core Web Application Factories. The testing framework code will spin up an in-process Web Host, register mocked controller interfaces, and set up an interceptor that will pick up a mock object for the called controller.

Advantages Over WireMock

  • Better performance compared to spinning up an HttpListener on localhost
  • Tests can be run in parallel. A single service endpoint can be mocked per test method, i.e. each test method will have it's own Mock object configured
  • Less effort to set up mocks!

Using Service Mocks in Tests

Add WebApplicationFixture.WithMockedServices call to AssemblyInitialize method and register all controller interfaces being mocked.

[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
    => WebApplicationFixture.WithMockedServices<IMockController>(MockFactory).Load();

Get service mock instance:

_mock = ServiceMockFixture.Get<IMockController>();

Setup the mock:

string receivedValue = null;
_mock.Setup(c => c.Action(It.IsAny<string>())).Returns(() => Task.CompletedTask).Callback<string>(value => receivedValue = value);
_mock.Setup(c => c.GetResponse()).ReturnsAsync(() => new MockServiceModel { Message = TestContext.TestName });
_mock.Setup(c => c.GetResponse(It.IsAny<string>()))
                .ReturnsAsync<string, IMockController, MockServiceModel>(value => new MockServiceModel { Message = value });

Now you are ready to make HTTP requests to the mocked service!

_service = GetTestApiClient<IMockController>();
await _service.Action(TestContext.TestName);

Custom Request Factory

If you are using a custom IRequestFactory for your IMockController then you will also need to add following to your request factory:

requestTrace.SetTraceProperties(message);
message.Properties.Add("HostId", info.Host);

Keep in mind that if IMockController is a contract for non-majority api, for example Alloy or Galileo, Then you might need to add environment check around these lines of code, as we shouldn't expose our request traces to external integrations. In addition some integration might even fail your requests for sending extra headers. Galileo is one such example:
if (_hostingEnvironment.IsDevelopment()) 
{
    requestTrace.SetTraceProperties(message);
    message.Properties.Add("HostId", info.Host);
}

How It Works

Check the code! ;)