Reputation: 345
I'm trying to do basically what the title says in order to unit test my api controller, but I have problems finding the proper way and can't afford spending too much time on this. Here is my code.
[TestMethod]
public void Should_return_a_valid_json_result()
{
// Arrange
Search search = new Search();
search.Area = "test";
string json = JsonConvert.SerializeObject(search);
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
request.Setup(r => r.HttpMethod).Returns("POST");
request.Setup(r => r.InputStream.ToString()).Returns(json);
context.Setup(c => c.Request).Returns(request.Object);
var controller = new UserController();
controller.ControllerContext = new HttpControllerContext() { RequestContext = context };
//more code
}
Last line returns Error CS0029 Cannot implicitly convert type 'Moq.Mock System.Web.HttpContextBase' to 'System.Web.Http.Controllers.HttpRequestContext'.
I am also not sure about the Moq syntax I should use, other questions,examples and Moq Documentation didn't help me much.
Upvotes: 7
Views: 17572
Reputation: 640
I'm using this approach
My API controller
[Route("[controller]")]
[ApiController]
public class FetchLeadStatusController : ControllerBase
{
private readonly IFtchDgLdStsExecution _ftchDgLdStsExecution;
public FetchLeadStatusController(IFtchDgLdStsExecution ftchDgLdStsExecution)
{
this._ftchDgLdStsExecution = ftchDgLdStsExecution;
}
[HttpPost]
public async Task<IActionResult> Post()
{
try
{
StreamReader requestReader = new StreamReader(Request.Body);
dynamic request = JObject.Parse(await requestReader.ReadToEndAsync());
FtchDgLdStsReturn Casetatus = await _ftchDgLdStsExecution.ValidateFtchDgLdSts(request);
return Ok(Casetatus);
}
catch (Exception ex)
{
return BadRequest();
}
}
My test class
[TestClass]
public class FetchLeadStatusControllerTest
{
private Mock<IFtchDgLdStsExecution> _FtchDgLdStsExecution;
private Fixture _fixture;
private FetchLeadStatusController _controller;
public FetchLeadStatusControllerTest()
{
_fixture = new Fixture();
_FtchDgLdStsExecution = new Mock<IFtchDgLdStsExecution>();
_controller = new FetchLeadStatusController(_FtchDgLdStsExecution.Object);
}
[TestMethod]
public async Task Post_FetchDigiLeadStatus_ReturnOK()
{
var request_body = new RequestBody();
request_body.LeadID = "1000078";
var json = JsonConvert.SerializeObject(request_body);
var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var httpContext = new DefaultHttpContext()
{
Request = { Body = stream, ContentLength = stream.Length }
};
var controllerContext = new ControllerContext { HttpContext = httpContext };
var ftch_Return = _fixture.Create<FtchDgLdStsReturn>();
_FtchDgLdStsExecution.Setup(x => x.ValidateFtchDgLdSts(json)).ReturnsAsync(ftch_Return);
_controller.ControllerContext = controllerContext;
var result = await _controller.Post();
Assert.IsNotNull(result);
}
}
Upvotes: 0
Reputation: 261
I'm using this approach
var json = JsonConvert.SerializeObject(request);
var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var httpContext = new DefaultHttpContext()
{
Request = { Body = stream, ContentLength = stream.Length }
};
var controllerContext = new ControllerContext { HttpContext = httpContext };
var controller = new Your_Controller(logic, logger) { ControllerContext = controllerContext };
Upvotes: 15
Reputation: 247521
No need for mock here if the intention is just to pass a request.
[TestMethod]
public void Should_return_a_valid_json_result() {
// Arrange
var search = new Search();
search.Area = "test";
var json = JsonConvert.SerializeObject(search);
var request = new HttpRequestMessage();
request.Method = HttpMethod.Post;
request.Content = new StringContent(json);
var controller = new UserController();
controller.Request = request;
//more code
}
Upvotes: 8