Home > Mobile >  Unit testing - casting an OkResult. What happens if the object cannot be cast to OkResult?
Unit testing - casting an OkResult. What happens if the object cannot be cast to OkResult?

Time:04-11

I've just started Unit Testing and I'm having some trouble understanding how should I write them.

I have this code

[Theory]
        [InlineData("00000000-0000-0000-0000-000000000001")]
        [InlineData("00000000-0000-0000-0000-000000000002")]
        public void Delete_Intern(Guid id)
        {
            _internService.Setup(x => x.Delete(It.IsAny<Guid>())).Returns(true);

            var actual = (OkResult) _internsController.DeleteIntern(id);
            Assert.True(actual is OkResult);
        }

        [Theory]
        [InlineData("00000000-0000-0000-0000-000000000000")]
        [InlineData("00000000-0000-0000-0000-000000000005")]
        public void Delete_Intern_ShouldFail(Guid id)
        {
            _internService.Setup(x => x.Delete(It.IsAny<Guid>())).Returns(false);

            var actual = (OkResult)_internsController.DeleteIntern(id);
            Assert.False(actual is OkResult);
        }

which tests this method:

[HttpDelete("{id}")]
        public IActionResult DeleteIntern(Guid id)
        {
            bool deleted = _internService.Delete(id);
            if (deleted == false)
            {
                return NotFound("Intern cannot be found");
            }
            return Ok();
        }

how should I write the ShouldFail method so it will be able to do that cast?

Right now, I'm getting an exception, saying that I cannot cast an object of type NotFoundResult to an OkResult.

I tried casting it to ObjectResult, then checking if it is an OkResult. But it doesn't work, because OkResult cannot be cast to ObjectResult.

Thanks.

CodePudding user response:

The NotFound() method will return NotFoundResult, if you want to test it just cast asNotFoundResult instead of OKResult.

Because NotFoundResult isn't equal to OKResult

[Theory]
[InlineData("00000000-0000-0000-0000-000000000000")]
[InlineData("00000000-0000-0000-0000-000000000005")]
public void Delete_Intern_ShouldFail(Guid id)
{
    _internService.Setup(x => x.Delete(It.IsAny<Guid>())).Returns(false);

    var actual = (NotFoundResult)_internsController.DeleteIntern(id);
    Assert.True(actual is NotFoundResult);
}

Or you can use StatusCodeResult type from _internsController.DeleteIntern because both of NotFoundResult and OKResult are inherit that.

[Theory]
[InlineData("00000000-0000-0000-0000-000000000000")]
[InlineData("00000000-0000-0000-0000-000000000005")]
public void Delete_Intern_ShouldFail(Guid id)
{
    _internService.Setup(x => x.Delete(It.IsAny<Guid>())).Returns(false);

    StatusCodeResult actual = _internsController.DeleteIntern(id);
    Assert.False(actual is OKResult);
}

CodePudding user response:

I personally like this use the Assert.IsAssignableFrom<T> because you can directly assert that you get the proper response back. It also casts the result which allows you to easily assert the contents of it afterwards.

Example for your OKResult:

[Theory]
[InlineData("00000000-0000-0000-0000-000000000001")]
[InlineData("00000000-0000-0000-0000-000000000002")]
public void Delete_Intern_ShouldFail(Guid id)
{
    _internService.Setup(x => x.Delete(It.IsAny<Guid>())).Returns(false);

    var result = _internsController.DeleteIntern(id);

    var notFound = Assert.IsAssignableFrom<NotFoundObjectResult>(result);
    var response = Assert.IsAssignableFrom<string>(notFound.Value);
    Assert.Equal("Intern cannot be found", response);
}

I added a check on the string in the response as well just to illustrate how easy it would be to add such checks.

  • Related