lundi 2 novembre 2015

Unit testing existing codebase

I'm working on a medium sized (ASP.NET MVC) project with lots of business logic code since the business rules for the application are quite complex at times.

I'm using the following solution structure:

  • ClientName.Web (MVC website)
  • ClientName.Interfaces (defines the business logic methods)
  • ClientName.BusinessLogic (should probably be called "Services" since I'm using entity framework here)
  • ClientName.Model (contains the EF DbContext class, enums etc..)
  • ClientName.Tests (unit tests project)

For accessing the (MSSQL) database, I'm using Entity Framework v. 6.

Now, most of the business logic methods are already written and working as they should. However, the size of the codebase is now at a point, where I'm fixing a feature and then breaking another which is far from ideal. What I should've done from the very beginning was to write unit tests for the business logic methods, taking a TDD approach.

Due to this, I want to try and bring in unit tests for the existing (and future) business logic methods and I have read about Moq and discovered this blog post on MSDN which I found interesting. There's one problem, though: my DbContext gets injected into the business logic classes (I run one DbContext per http request) which are used to perform the CRUD operations. A business logic class could look like this:

public class PersonBusiness
{
    private readonly MyContext _myContext;

    public PersonBusiness(MyContext myContext)
    {
        _myContext = myContext;
    } 

    public IEnumerable<PersonResponsibility> GetResponsibilities()
    {
        return _myContext.PersonResponsibilities.Where(x => x.IsActive).ToList();
    }

    public void CreatePerson(string name)
    {
        Person person = new Person() { Name = name };
        _myContext.People.Add(person);
        _myContext.SaveChanges();
    }
}

(This is just a very simply example, some of the BL methods are absurd complex with reads from N tables etc)

As far as I understand, I need a fake DbContext for testing which Moq can help me with, but what I don't get is how I use the fake DbContext with my business logic classes since it expects a type of MyContext. Is there a way that I can use my existing methods, but with a fake context instead?

Also, this is a fairly large database with 20 - 25 tables. Do I have to create the mock data manually for each table, for each test I run, or is there some other way "mock" it? Some tests will involve i.e. 7 different tables which makes for a lot of manual mock data :-)

Any help/hint is greatly appreciated.

Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire