views:

689

answers:

6

Hi folks,

what's the best practice for creating test persistence layers when doing an ASP.NET site (eg. ASP.NET MVC site)?

Many examples I've seen use Moq (or another mocking framework) in the unit test project, but I want to, like .. moq out my persistence layer so that my website shows data and stuff, but it's not coming from a database. I want to do that last. All the mocking stuff I've seen only exists in unit tests.

What practices do people do when they want to (stub?) fake out a persistence layer for quick and fast development? I use Dependency Injection to handle it, and have some hard coded results for my persistence layer (which is really manual and boring).

What are other people doing? Examples and links would be awesome :)

UPDATE

Just a little update: so far i'm getting a fair bit of milage out of having a fake repository and a sql repository - where each class impliments an interface. Then, using DI (i'm using StructureMap), I can switch between my fake repository or the sql repository. So far, it's working well :)

(also scary to think that I asked this question nearly 11 months ago, from when i'm editing this, right now!)

+2  A: 

Assuming you're using the Repository pattern from Rob Conery's MVC Store Front:

http://blog.wekeroad.com/mvc-storefront/mvc-storefront-part-1/

I followed Rob Conery's tutorial but ran into the same want as you. Best thing to do is move the Mock Repositories you've created into a seperate project called Mocks then you can swap them out pretty easily with the real ones when you instantiate your service. If your feeling adventurous you could create a factory that takes a value from the config file to instantiate either a mock or a real repository,

e.g.

public static ICatalogRepository GetCatalogRepository(bool useMock)
{
     if(useMock)
          return new FakeCatalogRepository();
     else
          return new SqlCatalogRepository();
}

or use a dependency injection framework :)

container.Resolve<ICatalogRepository>();

Good luck!

EDIT: In response to your comments, sounds like you want to use a list and LINQ to emulate a db's operations e.g. GetProducts, StoreProduct. I've done this before. Here's an example:

public class Product
{
     public int Identity { get; set; }
     public string Name { get; set; }
     public string Description { get; set; }
     //etc
}

public class FakeCatalogRepository()
{
     private List<Product> _fakes;

     public FakeCatalogCatalogRepository()
     {
          _fakes = new List<Product>();

          //Set up some initial fake data
          for(int i=0; i < 5; i++)
          {
              Product p = new Product
              {
                 Identity = i,
                 Name = "product"+i,
                 Description = "description of product"+i
              };

              _fakes.Add(p);
          }
     }

     public void StoreProduct(Product p)
     {
         //Emulate insert/update functionality

         _fakes.Add(p);
     }

     public Product GetProductByIdentity(int id)
     {
          //emulate "SELECT * FROM products WHERE id = 1234
          var aProduct = (from p in _fakes.AsQueryable()
                         where p.Identity = id
                         select p).SingleOrDefault();

          return aProduct;
     }
}

Does that make a bit more sense?

Rob Stevenson-Leggett
Yep, i'm using the Repository pattern from Rob's Store Front. Exactly. The thing is, i didn't understand his Mock repository .. cause he's using mocks and hard coding. I just didn't get it. i was hoping that i could mock the memory db .. but i failed :( cont...
Pure.Krome
Pure.Krome
Maybe it's more elegant with DI.
boj
I'm already using DI ... but this means i would inject a fake repository instead of using mocks?
Pure.Krome
You seem to be confused between Mocks and Fakes, generally people use the terms interchangeably. If you use DI to inject a fake/mock repository you don't have to change your calling code when you deploy, just your configuration (to point at the real repository class).
Rob Stevenson-Leggett
+1  A: 

Boring or not, I think you're on the right track. I assume you're creating a fakeRepository that is a concrete implementation of your IRepository which in turn is injected into your service layer. This is nice because at some point in the future when you're happy with the shape of your entities and the behavior of your services, controllers, and views, you can then test drive your real Repositories that will use the database to persist those entities. Of course the nature of those tests will be integration tests, but just as important if not more so.

One thing that may be less boring for you when the time comes to create your real repositories is if you use nHibernate for your persistence you will be able let nhibernate generate your database after you create the nhibernate maps for your entities, assuming you don't have to use a legacy schema.

For instance, I have the following method that is called by my SetUpFixture to generate my db schema:

public class SchemaBuilder
{
   public static void ExportSchema()
    {
        Configuration configuration = new Configuration();
        configuration.Configure();
        new SchemaExport(configuration).Create(true, true);
    }
}

and my SetUpFixture is as follows:

[SetUpFixture]
public class SetUpFixture
{
    [SetUp]
    public void SetUp()
    {
        SchemaBuilder.ExportSchema();
        DataLoader.LoadData();
    }
}

where DataLoader is responsible for creating all of my seed data and test data using the real respoitory.

This probably doesn't answer your questions but I hope it serves to reassure you in your approach.

Greg

Greg Banister
A: 

I've gone the route of creating tables and data during a setup method in a unit test class, running tests, then doing clean up during the teardown. Yes, this method works, but if you really end up using your unit tests for debugging purposes, invariably you will run the setup, debug something then stop in the middle without doing the teardown. It's very brittle and you will probably end up (in the long run) with bad data in your test database and/or unusable unit tests. I personally think its best to mock the database layer using a mocking framework. I do understand that sometimes it's best to do logic in the database. For these cases you can use a tool like DBFit to write tests for your database layer.

--Matt

Matthew Timbs
i don't see this as unit tests, but intergration testing. it's also more pain (for me) than what it's worth, IMO. soz.
Pure.Krome
A: 

Although I'm not using Asp.Net or the MVC framework I do have the need to test services without hitting the database. Your question triggered the writing up of a short (ok, maybe not so short) summary of how I do it. Not claiming it's the best or anything, but it works for us. We access data through a repository and when required we plug in an in-memory repository as explained in the post.

http://blogs.microsoft.co.il/blogs/kim/archive/2008/11/14/testable-data-access-with-the-repository-pattern.aspx

Kim Major
A: 

Has anyone ever created a fully stubbed / fake repository for their site .. and the site is very usuable .. and then at the end, create the DB and then inject that in?

Pure.Krome
A: 

I am using a complete in memory database with SQLite and ActiveRecord. Basically we delete and re-create the database before every integration test is being run, so that the data is always in a known state. The contents of the database are inserted through code. So an example would be like this:

ActiveRecord.Initalize(lots of parameters)
ActiveRecord.DropSchema();
ActiveRecord.CreateSchema();

and then we just add lots of customers or whatever, DDD style:

customerRepository.Save(customer);

Another way to solve this could be using NDbUnit to maintain the state of the database.

Microserf