Search code examples
asp.netmstestasp.net-mvc-5justmock

Casting ActionResult as HttpNotFoundResult returns null


I have a unit test for my controller that asserts that an HttpNotFoundResult is returned when an instance of the model is not found. The problem is, the actual code in the controller is working as intended, but my unit test is not. When casting the ActionResult as HttpNotFoundResult, it returns null, thus my unit test is failing.

Controller code:

public ActionResult Delete(int? id)
        {
            if(id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Forum forum = forumRepository.GetForumById(id.GetValueOrDefault());
            if(forum == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.NotFound);
            }
            return View(forum);
        }

Test method:

 [TestMethod]
        public void GetDeleteShouldReturn404IfForumNotFound()
        {
            // Arrange
            var forumRepository = Mock.Create<IForumRepository>();
            Mock.Arrange(() => forumRepository.GetForums())
                .Returns(new List<Forum>() {
                    new Forum { ForumId = 1, Title = "General Forum", Description = "Place to discuss general stuff", Sequence = 2 },
                    new Forum { ForumId = 2, Title = "Gaming", Description = "Let's talk about gaming", Sequence = 1 },
                    new Forum { ForumId = 3, Title = "Web Development", Description = "ASP.NET is pretty cool", Sequence = 3 }
                }).MustBeCalled();

            // Act
            ForumController controller = new ForumController(forumRepository);
            ActionResult result = controller.Delete(5) as HttpNotFoundResult;

            // Assert
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(HttpNotFoundResult));
        }

The Assert.IsNotNull fails. I have also tried the following with the same result:

HttpNotFoundResult result = controller.Delete(5) as HttpNotFoundResult;

This boggles my mind because I have seen nearly the same code in several examples:

http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net-mvc-3-using-httpnotfoundresult-in-controller-tests.aspx

Is there something I am doing wrong?

Edit:

The issue was that I was not mocking GetForumById(), changing the test code to the following worked:

[TestMethod]
        public void GetDeleteShouldReturn404IfForumNotFound()
        {
            // Arrange
            var id = 10;
            Forum forum = null;

            var forumRepository = Mock.Create<IForumRepository>();

            Mock.Arrange(() => forumRepository.GetForumById(id))
                .Returns(forum)
                .MustBeCalled();

            // Act
            ForumController controller = new ForumController(forumRepository);
            var result = controller.Delete(id) as HttpNotFoundResult;

            // Assert
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(HttpNotFoundResult));
        }

Solution

  • It's because HttpNotFoundResult derives from HttpStatusCodeResult, not the other way around. You are making an invalid downcast, that makes as statement return null.