cannelle28
cannelle28

Reputation: 307

How to mock service injected by HttpContext.RequestServices.GetService<> in derived controller?

I have base Api Controller defined like this

[ApiController]
public abstract class BaseController : ControllerBase
{
    private IMediator _mediator;

    protected IMediator Mediator => _mediator ??= HttpContext.RequestServices.GetService<IMediator>();
}

Auth controller derived from BaseController

public class AuthController : BaseController
{
    [HttpPost(ApiRoutes.Auth.Register)]
    public async Task<IActionResult> Register(UserRegistrationRequest request)
    {
        var response = await Mediator.Send(new UserRegistrationCommand(request.Email, request.Password));

        return Ok(response);
    }
}

How should mock IMediator service in unit tests? When services were injected using constructor DI I've just passed mocked services to constructor in tests, but in this scenario I'm not sure what to mock, probably HttpContext?

Upvotes: 5

Views: 3480

Answers (3)

Yola
Yola

Reputation: 19083

var features = new FeatureCollection();
var serviceProvidersFeature = new ServiceProvidersFeature();
features.Set<IServiceProvidersFeature>(serviceProvidersFeature);
var context = new DefaultHttpContext(features);
// One can create real service provider or use mock
var serviceProvider = new Mock<IServiceProvider>();
serviceProvidersFeature.RequestServices = serviceProvider.Object;
serviceProvider.Setup(m => m.GetRequiredService<...>()).Returns(new ...())

Upvotes: 0

sametcekin
sametcekin

Reputation: 91

You can use this way for passing parameter to your controller or etc.

Mock<IMediatr> _mediatrMock;
AuthController _controller;
public AuthControllerTest()
{       
    _mediatrMock = new Mock<IMediatr>();

    var httpContext = new Mock<HttpContext>();
    httpContext.Setup(x => x.RequestServices.GetService(typeof(IMediatr)))
        .Returns(_mediatrMock.Object);

    _controller = new AuthController();
    _controller.ControllerContext.HttpContext = httpContext.Object;
}

[Fact]
public async Task Register_ShouldReturnOk()
{
    var req= new UserRegistrationRequest();
    
    var result = _controller.Register(req);
    var resultObject = result as OkObjectResult;
    
    Assert.Equal(...);
}

Upvotes: 2

Jonathan Busuttil
Jonathan Busuttil

Reputation: 503

You should mock it using a library such as Moq or NSubstitute. Then wire up the methods using these libraries.

Upvotes: 1

Related Questions