简体   繁体   中英

Unit test for controller doesn't work as expected

I have created the following controller:

[HttpGet(“{provId}/m”)]
public async Task<IActionResult> GetMForProv (int provId)
{
   var result = await _mediator.Send(new GetMForProvQuery() { ProvId = provId });

   if (result == null)
   {
      return NotFound();
   }

   return Ok(result);
}

And the following unit test:

public class GetMForProvTest
{
   private readonly ProvController _sut;
   private readonly Mock<IMediator> _mediator;
   private readonly Mock<IConfiguration> _configuration;

   public GetMForProvTest()
   {
      _mediator = new Mock<IMediator>();
      _configuration = new Mock<Iconfiguration>();

      _mediator.Setup(x => x.Send(It.IsAny<GetMForProvQuery>(), It.IsAny<CancellationToken>()))
           .ReturnsAsync(new CatDto());

      _sut = new ProvController(_mediator.Object, _configuration.Object);
   }

   [Fact]
   public async Task ShouldReturnNotFoundResult_AfterGetMForProv()
   {
      var result = await _sut.GetMForProv(123); // this providerId does not exist

      Assert.Equal(StatusCodes.Status404NotFound, (result as NotFoundObjectResult).StatusCode);
   }

When I run the above test, on the line Assert.Equal(…) I get

Object reference not set to an instance of an object.

(… as NotFoundObjectResult returned null.

How can I get this work?

The answer was supplied by Chetan in the comments:

I think you need to cast to NotFoundResult instead of NotFoundObjectResult

You're not passing an object in return NotFound() so you should use NotFoundResult instead. The As operator is returning null which is why you're getting the exception. Update the Assert to:

Assert.Equal(StatusCodes.Status404NotFound, (result as NotFoundResult).StatusCode);

This was tested and is working for me using your original setup with this:

_mediator.Setup(x => x.Send(It.IsAny<GetMForProvQuery>(), It.IsAny<CancellationToken>()))
         .ReturnsAsync(() => null);

Original answer before you clarified you're using optional parameters

Are you sure you're setting up the correct overload for _mediator.Send ? It looks like you're setting up a different overload for Send in:

_mediator.Setup(x => x.Send(It.IsAny<GetMForProvQuery>(), It.IsAny<CancellationToken>()))...

which takes 2 parameters. However, you're calling it with a single argument in the controller:

var result = await _mediator.Send(new GetMForProvQuery() { ProvId = provId })

Could you try setting up the single argument overload and pass an action returning null:

_mediator.Setup(x => x.Send(It.IsAny<GetMForProvQuery>()))
           .ReturnsAsync(() => null);

Try to fix line:

.ReturnsAsync(new CatDto());

To

.ReturnsAsync((CatDto)null);

Because you return CatDto object and the result of casting (result as NotFoundObjectResult) is null

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM