I'm building a Web API in ASP.NET Core, and I want to unit test the controllers.
I inject an interface for data access, that I can easily mock. But the controller has to check the headers in the Request for a token, and that Request doesn't seem to exist when I simply instantiate the controller myself, and it is also get-only, so I can't even manually set it. I found lots of examples to mock an ApiController, but that isn't .NET core. Also many tutorials and examples of how to unit test .net core controllers, but none actually used the HttpRequest.
I built an MCVE to demonstrate this:
[Produces("application/json")] [Route("api/Players")] public class PlayersController : Controller { private IAccessor accessor; public PlayersController(IAccessor ac = null):base() { accessor = ac ?? AccessorFactory.GetAccessor(); } /// <summary> /// Get all players. Must be logged in. /// </summary> /// <returns>Ok or Unauthorized.</returns> [HttpGet] public IActionResult Get() { Player client = accessor.GetLoggedInPlayer(Request.Headers["token"]); // NRE here because Request is null if (client == null) return Unauthorized(); return Ok(accessor.GetAllPlayers()); } }
I'm using Moq and MSTest in my test project, and inject a mocked IAccessor. How do I inject the Request, or initialize it with the controller? I guess my last resort would be reflection, but I really want to avoid that.
Mocking ResponsecreateResponse({ eventEmitter: require('events'). EventEmitter }); //Usage: somewhere in tests let next = sinon. spy(); getUsers(request, response, next); response. on('end|data|error', function(error){ //write tests in this close. });
If you've writing custom filters, routes, etc, you should unit test them, but not as part of your tests on a particular controller action. They should be tested in isolation.
Unit testing involves testing a part of an application in isolation from its infrastructure and dependencies. When you unit test controller logic, only the content of a single action or method is tested, not the behavior of its dependencies or of the framework itself.
When creating an instance of the controller under test, make sure to assign a HttpContext
that contains the required dependencies for the test to be exercised to completion.
You could try mocking a HttpContext
and providing that to the controller or just use DefaultHttpContext
provided by the framework
//Arrange var mockedAccessor = new Mock<IAccessor>(); //...setup mockedAccessor behavior //... var httpContext = new DefaultHttpContext(); // or mock a `HttpContext` httpContext.Request.Headers["token"] = "fake_token_here"; //Set header //Controller needs a controller context var controllerContext = new ControllerContext() { HttpContext = httpContext, }; //assign context to controller var controller = new PlayersController (mockedAccessor.Object){ ControllerContext = controllerContext, }; //Act var result = controller.Get(); //...
The above assumes you already know how to mock the controller dependencies like IAccessor
and was meant to demonstrate how to provide framework specific dependencies needed for the test.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With