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! ;)