Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC: testing a controller with XUnit

I am trying to use unit testing with XUnit for an ASP.NET v5 MVC v6 app. I can get simple unit testing on methods working. I would like to test Controllers. Right now, I have a HomeController with an Index action that returns the Home/Index view. I want to test that the Index view is the one that is returned.

Here is my current test file:

using Microsoft.AspNet.Mvc;
using Xunit;
using XUnitWithMvcSample.Controllers;

namespace XUnitWithMvcSample.Tests
{
    public class Tests
    {
        private HomeController _homeController;
        public Tests()
        {
            _homeController = new HomeController();
        }
        [Fact]
        public void IndexActionReturnsIndexView()
        {
            var result = _homeController.Index() as ViewResult;
            System.Console.WriteLine(result);
            Assert.Equal("Index", result.ViewName);
        }

    }
}

Here's Controllers/HomeController.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;


namespace XUnitWithMvcSample.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

When I run the test, it fails, since result.ViewName is null. It looks like result is just an empty ViewResult with nothing to do with _homeController. What do I need to do to get the test to find the Index view in HomeController?

like image 336
jmk22 Avatar asked Jan 13 '16 19:01

jmk22


People also ask

Should controllers be tested?

Controllers should typically check the ModelState property before doing anything. In some ways, this is good. Validation is moved outside the action method, so you can test it independently of the controller action method.

What is a best practice when unit testing a controller?

When unit testing controller logic, only the contents of a single action are tested, not the behavior of its dependencies or of the framework itself. Set up unit tests of controller actions to focus on the controller's behavior. A controller unit test avoids scenarios such as filters, routing, and model binding.

Should I use MSTest or xUnit?

XUnit vs. MSTest is concerned, the biggest difference between xUnit and the other two test frameworks (NUnit and MSTest) is that xUnit is much more extensible when compared to NUnit and MSTest. The [Fact] attribute is used instead of the [Test] attribute.


2 Answers

It sounds like you're trying to test functionality that's in the framework, rather than what's just in the method. All that's in the method is this:

return View();

So, literally, as long as a non-null ViewResult is returned, then the method does what it's expected to do:

// Arrange
var controller = new HomeController();

// Act
var result = controller.Index() as ViewResult;

// Assert
Assert.IsNotNull(result);

Linking that result to a view is part of the ASP.NET MVC Framework and happens outside of that method. Which means that it's not part of the method call itself, but happens outside the scope of the method. That puts it outside the scope of the test.

You'd have to set up a kind of running ASP.NET MVC application and test that application in order to test that functionality, which is more of a black box test than a unit test.

like image 182
David Avatar answered Oct 13 '22 02:10

David


It's a bit late answer but if you can change your action method like that, your test will work.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;


namespace XUnitWithMvcSample.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View("Index");
        }
    }
}
like image 20
Burak Altin Avatar answered Oct 13 '22 01:10

Burak Altin