Bartosz Chodyła
Bartosz Chodyła

Reputation: 85

ASP.NET MVC unit testing WEB API Post method: Request.RequestUri throws an exception

I want to test Web api 2 post method, which looks like this:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IHttpActionResult CreateEquipment(EquipmentDto equipmentDto)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        var equipment = Mapper.Map<EquipmentDto, Equipment>(equipmentDto);

        unitOfWork.Equipment.Add(equipment);
        unitOfWork.Complete();

        equipmentDto.Id = equipment.Id;

        return Created(new Uri(Request.RequestUri + "/" + equipment.Id), equipmentDto);
    }

I am using Moq and NUnit to test. My SetUp method and test method look like this:

    [SetUp]
    public void SetUp()
    {
        unitOfWork = new Mock<IUnitOfWork>();
        controller = new EquipmentController(unitOfWork.Object);
        Mapper.Initialize(c => c.AddProfile<MappingProfile>());
    }

    [Test]
    public void CreateEquipment_ModelIsValid_ReturnCreated()
    {
        var equipmentDto = new EquipmentDto();
        var equipment = Mapper.Map<EquipmentDto, Equipment>(equipmentDto);
        unitOfWork.Setup(uow => uow.Equipment.Add(equipment));
        unitOfWork.Setup(uow => uow.Complete());

        var result = controller.CreateEquipment(equipmentDto) as CreatedAtRouteNegotiatedContentResult<EquipmentDto>;

        Assert.IsNotNull(result);
    }

I am getting NullReferenceException in the controller's line:

  return Created(new Uri(Request.RequestUri + "/" + equipment.Id), equipmentDto);

equipment.Id and equipmentDto are not null. The null is Request, that's why Request.RequestUri throws an exception.

How to set up the Request properly to avoid the exception and pass the test? I would appreciate any help.

I know there is a similiar question: ASP.NET Testing Api controller: Uri(Request.GetEncodedUrl()...) returns null But that is related to ASP.NET Core and I coulnd't find out how to resolve the problem in ASP.NET MVC.

EDIT: Also tried to add this in the test method:

           var context = new Mock<HttpContextBase>();
        context.Setup(x => x.Request.Url).Returns(new Uri("/Equipment/New", UriKind.Relative));

But it didn't help.

Upvotes: 0

Views: 770

Answers (1)

Sergey Anisimov
Sergey Anisimov

Reputation: 895

You need to configure your controller with HttpRequestMessage like:

var request = new HttpRequestMessage()
{
    RequestUri = new Uri("http://localhost:5000/Equipment/New", UriKind.Absolute)
};

var controllerContext = new HttpControllerContext
{
    Request = request
};

var controller = new EquipmentController(unitOfWork.Object)
{
    ControllerContext = controllerContext
};

...

var result = controller.CreateEquipment(equipmentDto) as CreatedNegotiatedContentResult<EquipmentDto>;

Assert.NotNull(result);

Also note that you return CreatedNegotiatedContentResult from the endpoint but not CreatedAtRouteNegotiatedContentResult

Upvotes: 2

Related Questions