简体   繁体   中英

Integration Testing ASP.NET MVC Applications

I've never tested ASP.NET MVC3 applications before, although I have plenty of experience with NUnit/JUnit/etc. and TDD. My question is, what kind of strategies can I use to test MVC applications?

Edit: My focus here is primarily around test strategies, and also, with a focus on integration testing -- testing what real users will go through when they click through my application.

My setup is ASP.NET MVC with ORM (NHibernate or Dapper, depending on the project).

Is there a web-based test suite similar to NUnit? Should I write one? Or should I (somehow) try to break my application into a million little non-web DLLs and test those in NUnit? (Is that even possible with ActiveRecord/NHibernate as the ORM layer?)

What do you do to test this kind of app?

I looked at similar SO questions, and didn't find much, other than "here's how to test a controller."

There are different kinds of tests: unit, integration, acceptance, ...

If you are talking about unit tests, ASP.NET MVC is built with testability in mind. There are many articles illustrating those concepts. Here's one example . And another one . And yet another one . If you want your application to be unit testable you will have to design it in such a way that there is a weak coupling between the different layers. So for example you will abstract all data access behind interfaces that will be used by the controllers. You will use a DI framework which will pass a concrete implementation (NHibernate or whatever) into the controller and in the unit test you will be able to use a mocking framework to stub the data access layer and test this controller in complete isolation.

When we are talking about integration testing for ASP.NET MVC application there are two points for consideration:

  1. Testing suite should interact with application as users do using web browser
  2. Testing suite should be able to isolate (mock) different part of web application during test session.

If this is your case then here is my recipie:

  1. Host your web application using IIS Express using command line

     iisexpress.exe /path:[path] /port:[port] 
  2. Use Selenium web driver to emulate browser activity.

  3. Use SpecFlow to define user sessions in gherkin language
  4. Use Deleporter to mock web application components while it is running

I have written detailed article about this approach. There is also a github repo with this approach implemented.

I think it depende on what you want to test. If you want to test from the UI you need to use some kind of driver for the UI like Selenium or Watin .

If you also use Specflow together with one of these web drivers you could write specs as you do in ruby for example.

I myself would not go so far as testing through the UI since I consider the UI to change to much. I would focus driving acceptance thorugh the controllers in an MVC application and keep the controllers really small with a minimum amount of logic in them. I think the controllers should just provide some basic validation of the inputs and than delegate down to your application.

All this also depends on how complicated your application is, the main rule of thumb should be to keep it simple :).

If you're already familiar with Nunit / Junit and TDD those strategies simply need to be applied to unit testing an MVC web application.

There is no need to write a web based test suite, nor is their a need to break your application out into a "million" little non-web dll's. That being said, you still need to design your application to be testable.

A very simple controller test could look like the following. Note, that my example is making use of Moq for the repository / DI.

[Test]
public void Edit_Get_Should_Lookup_Contact_From_Repository_And_Return_Edit_View()
{
    // arrange
    var _repository = new Mock<IContactRepository>();

    var expectedContact = new Contact
    {
        First = "first",
        Last = "last",
        Email = "mail@test.com"
    };

    var mockContext = new Mock<ControllerContext>();
    _repository.Setup(x => x.GetById(It.IsAny<int>())).Returns(expectedContact);

    var controller = new ContactController(_repository.Object)
    {
        ControllerContext = mockContext.Object
    };

    // act
    var result = controller.Edit(1) as ViewResult;
    var resultData = (Contact)result.ViewData.Model;

    // assert
    Assert.AreEqual("Edit", result.ViewName);
    Assert.AreEqual(expectedContact.First, resultData.First);
    Assert.AreEqual(expectedContact.Last, resultData.Last);
    Assert.AreEqual(expectedContact.Email, resultData.Email);
}

[HttpGet]
public ActionResult Edit(int id)
{
    var contact = _repository.GetById(id);

    return View("Edit", contact);
}

If you would like some more examples of unit testing / mvc, browse through the nerd dinner sample application: http://nerddinner.codeplex.com/

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