3

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));
        }
Soldat1988
  • 67
  • 1
  • 7

1 Answers1

2

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

Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
  • What would you suggest I change the code to? I have tried using 'return HttpNotFound()' in the controller (which returns an instance of the HttpNotFoundResult class), but that doesn't work either. – Soldat1988 Mar 13 '14 at 14:15
  • @Soldat1988 What does `controller.Delete(5)` return? What's its type? – Ufuk Hacıoğulları Mar 13 '14 at 14:26
  • In this case, it should be returning a value of type `HttpNotFoundResult` if I use `return HttpNotFound()` in the controller action. – Soldat1988 Mar 13 '14 at 14:29
  • @Soldat1988 What does it return when you debug your code? – Ufuk Hacıoğulları Mar 13 '14 at 14:30
  • Debugging the controller code shows that it returns a value of type `HttpNotFoundResult`. When I debug the test, `result` is `null`. – Soldat1988 Mar 13 '14 at 14:45
  • @Soldat1988 Yet, the test still fails on `Assert.IsNotNull(result);` line? – Ufuk Hacıoğulları Mar 13 '14 at 14:47
  • 1
    Yes. After further debugging, running the actual code gives me the correct result. Running the test, it never enters the `if (forum == null)` block, so the forum is not null. I don't know why this would be different between the test and production code, though. – Soldat1988 Mar 13 '14 at 14:53
  • @Soldat1988 Your test has an error then. You are not mocking GetForumById method but somehow it's returning a non null value. – Ufuk Hacıoğulları Mar 13 '14 at 14:55
  • This was correct. I needed to mock GetForumById to return a null value when a forum id was passed in that does not exist. I have updated my original post to show the correct code. Thanks! – Soldat1988 Mar 13 '14 at 15:10