Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing ASP.NET MVC with Data

We have an insanely data driven application. We want to unit test the application but developers are resistant to building entirely fake repositories because of the volume of data. I don't really blame them.

Understand that we are retrofitting tests into an existing application. If we were starting over we would make a ton of architectural changes to facilitate better unit testing with fake repositories.

We would like to distribute a known mdf file with the tests, copy it, and use that for performing our tests. Is there an approved technique for this? I'm familiar with embedding resources into the test dll, but not with embedding mdf's--if that can even be done.


A solution (sort of):

I ended up taking the DataContextWrapper from Andrew Tokeley's post on mocking Linq data contexts (http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx) and created a FakeDataContext.cs that is basically a bunch of Lists.

I wrote a truly barbaric T4 template (think "select * FROM <#=table.BaseClass.QualifiedName#>") to copy the data from a known good database to create a huge class full of stuff like:

List<Customer> _customers = new List<Customer>();
_customers.Add(new Customer(){CustomerId = 1, CustomerName = "ACME"});

etc.

The class is 25K lines but since t4 writes all those lines, who cares? It allows us to mock just the data context, so we can test our linq against the fake context with some reasonable assurance we got the queries right. The original devs put a ton of business logic in the repo, so it allows us to test the logic against known good data.

like image 267
Code Silverback Avatar asked Dec 15 '10 15:12

Code Silverback


People also ask

Should controllers be unit tested?

If you've writing custom filters, routes, etc, you should unit test them, but not as part of your tests on a particular controller action. They should be tested in isolation.


1 Answers

Can you set up a test database on a shared server so you don't have to deploy mdf files?

Also, can you wrap all unit tests with TransactionScope?

I've used a test database in my company that contained an well known reference data for all the tests and created a base class for integration tests like that:

[TestClass]
public class ServiceTest
{
    private TransactionScope Transaction { get; set; }

    [TestInitialize]
    public virtual void TestInitialize()
    {
        Transaction = new TransactionScope();
    }

    [TestCleanup]
    public virtual void TestCleanup()
    {
        Transaction.Dispose();
    }
}

Each test will rollback all it's changes so there's no problem with test data polluting the database.

like image 85
Jakub Konecki Avatar answered Oct 23 '22 03:10

Jakub Konecki