Showing posts with label unit testing. Show all posts
Showing posts with label unit testing. Show all posts

Oct 21, 2011

Setup SQL Server Compact 4 to unit test NHibernate related code

Most of the time to fake data base SQL lite data base is used. But it has certain differences from SQL server. With release of SQL Compact 4 it becomes really good choice to mock data base calls. So in this post I will describe a way of setting up NHibernate to work with SQL CE local data base. So here are our goals:

  1. Each test fixture has its own fresh DB instance
  2. NHibernate SessionFactory is same for all the tests (performance is still important in tests)
  3. Caching of NHibernate doesn’t stands on isolation way (each test will have clean factory, without any cached entities)
  4. Works just after getting from source control with no additional configuration

First of all we need to install sql ce tools for visual studio. After done that we can add an empty data base file to our tests project:

Sql server compact 4.0 local data base

lets call it db. This file is going to be the one that is going to be copied for each test and where NHibernate will create its tables.

Now lets create a base class for tests that are going to use NHibernate:

public class DbTests
{
    protected static ISessionFactory factory;
    static Configuration nhConfig;

    static DbTests()
    {
        File.Copy("db.sdf", "Temp.sdf", true);
        nhConfig = NhConfigure();
        factory = nhConfig.BuildSessionFactory();
    }

    [TestFixtureSetUp]
    public void Setup()
    {
        File.Copy("db.sdf", "Temp.sdf", true);
        new SchemaExport(nhConfig).Execute(true, true, false);
    }

    [TestFixtureTearDown]
    public void TearDown()
    {
        File.Delete("Temp.sdf");
    }

    static Configuration NhConfigure()
    {
        DomainMapper mapper = new DomainMapper();
        HbmMapping mappings = mapper.CompileMappingFor(new[] { typeof(TestEntity) });

        var configuration = new Configuration();
        configuration.SessionFactory()
            .Integrate.Using<MsSqlCe40Dialect>()
            .Connected.By<SqlServerCeDriver>()
            .Using("Data Source=Temp.sdf");

        configuration.AddDeserializedMapping(mappings, "domain");
        
        return configuration;
    }
}

What is done here is pretty straight forward. Each test fixture will get its own empty data base with new schema installed.

Also you will need to install SqlServerCompact package from nuget in order to get SqlServerCeDriver support.

There is an interesting bug when using identity columns with SQL CE. You can get NHibernate.AssertionFailure : null identifier exception. Here is how you can solve it.

The last thing we want to take care about is NHibernate cache. Each test probably will have its own ISession instance, so only second level caching should be handled. Here is how we can clean up it:

static void ClearCache()
{
    factory.EvictQueries();
    foreach (var collectionMetadata in factory.GetAllCollectionMetadata()) 
        factory.EvictCollection(collectionMetadata.Key);
    foreach (var classMetadata in factory.GetAllClassMetadata()) 
        factory.EvictEntity(classMetadata.Key);
}

Just add this method call to Setup and that it. As always working sample attached:

Source code sample doesn’t contain nuget packages and uses this way of working. So don’t be scared of everything red in ReSharper after open solution. Just build it.

Jul 22, 2011

Slides and code

I promised to publish slides and code from my talk about unit testing. Here they are:

And a source code:

Apr 12, 2011

Unit testing classes with a lot of dependencies

I’m sure every TD developer will scream that it’s not right to have classes with a lot of dependencies. I agree with you, but it happens. It happens for example in MVP pattern for ASP.NET, or for controllers in MVC.

Why it happens? The main reason I think are unnecessary abstractions. Many applications have interface like IRepository<T> : where T : IEntity. Such interface seams to be very useful. It gives you strongly typed access to the entities, and gives you ability to put common methods there (like Get<T>(int id)). Everything looks good so far. We configure our application to use IoC container and don’t bother with dependencies:

public ProductsController : Controller
{
    private readonly IRepository<Product> productsRepository;

    public ProductsController(IRepository<Product> productsRepository)
    {
        this.productsRepository = productsRepository;
    }

    public ActionResult Index()
    {
        var products = productsRepository.GetAll();
        return View(products);
    }
}

Everything looks good so far and we are able to write very simple unit test for it. Its easy to mock GetAll() method and verify that View.Model contains exact the same collection that returned from repository.

But then you need to create a Create method that requires getting list of all categories that could be assigned to product. And all of a sudden you have two dependencies:

public ProductsController : Controller
{
    private readonly IRepository<Product> productsRepository;
    private readonly IRepository<Category> categoriesRepository;

    public ProductsController(IRepository<Product> productsRepository, IRepository<Category> categoriesRepository)
    {
        this.productsRepository = productsRepository;
        this.categoriesRepository = categoriesRepository;
    }

    public ActionResult Index()
    {
        var products = productsRepository.GetAll();
        return View(products);
    }

    public ActionResult Create()
    {
        var categories = categoriesRepository.GetAll();
        ViewBag.Categories = categories;
        return View();
    }
}

Its still looking good. But only if you have 2-3 tests that are using ProductsController constructor with 1 parameter. When you have 20 of those its becoming a nightmare to add new dependency in constructor.

I do understand that its not best example of why a lot of dependencies happens, but its real one. Its very easy to have up to 4-6 decencies in constructor. And to do with it in tests? Each test needs to set 2 or 3 of them and he doesn’t cares about other. My first approach was creating a helper methods as such:

public ProductsController GetController(IRepository<Product> productsRepository)
{
    return new ProductsController(productsRepository, Mock.Of<IRepository<Category>>);
}

Its perfectly works for classes with less then 3 dependencies. But even there the problem still exists. Consider mocking of current HttpContext.Current.User.Identity. It may happen that each controller action needs access to it, but most of tests doesn’t care what is going to be returned as current user. You will need to copy paste mocking code in each of such methods, or put some complex chain of methods calling each other to get default user for all test controllers.

What I prefer to do now is having a simple factory for controllers (presenters) in test class:

internal class ProductsControllerFactory()
{
    public ProductsControllerFactory()
    {
        this.CategoriesRepsitory = Mock.Of<IRepository<Category>>();
        this.ProductsRepository = Mock.Of<IRepository<Product>>();
        
        // you can put all default stubs here
    }

    public ProductsController GetController()
    {
        return new ProductsController(this.CategoriesRepository, 
                                      this.ProductsRepository);
    }

    public IRepository<Category> CategoriesRepsitory { get; set; }

    public IRepository<Product> ProductsRepository { get; set; }
}

So you end up with having constructor call in one place. Adding a dependency won’t affect existing tests, it will affect only controller factory. Each test can easily set dependency it needs and ignore dependencies it doesn’t cares about.

Nov 6, 2009

Inversion of control. Управление зависимостями.

Данный пост является некоторым следствием работы над последним проектом. В этом проекте использовалась S#arp архитектура, которая обеспечивает отличную возможность для юнит тестирования и каркас для создания корпоративных веб приложений. Так же крайне полезно будет прочесть статью касающуюся зависимостей. Я считаю что разобраться в чем то лучше всего позволяет попытка объяснить это другому. Именно это и я и хочу сделать.

Рассмотрим пример программы. Пусть приложению необходима некоторая система ведения логов. Логи сохраняются в файл для дальнейшего анализа. Для подобных требований вполне логично было бы использовать следующий код:

public class Logger 
{ 
 public void LogMessage(string message) 
 { 
  using(FileStream fileStream = new FileStream("log.txt", FileMode.Append, FileAccess.Write)) 
  { 
   StreamWriter writer = new StreamWriter(fileStream); writer.Write(message); 
    }
 } 
} 

Данный код работает, и работает вполне нормально. Вы спокойно выполняете дальнейшие требования, другие девелоперы используют этот класс для записи логов. Через месяц плодотворной работы оказывается, что логов слишком много, и некоторые особо важные записи следует делать не в файл, а в базу данных.

Получив такое требование конечно хотелось бы добавить новый метод LogMessage(string message, bool storeInDataBase), который принимает дополнительный параметр типа bool и если он true пишет все что надо в базу.

Проблема в этом подходе я думаю уже видна – если в дальнейшем мы захотим писать не только базу данных и в файл, но в Windowns EventLog, то что, добавлять еще один флаг?

На данный момент диаграмма зависимостей будет выглядеть следующим образом:

image

Наш класс Logger напрямую зависит от файловой системы. Чтобы избавится от этой зависимости можно использовать принцип Inversion of control. Для этого выделим интерфейс, который будет отвечать за сохранение информации в лог:

public interface ILogContainer 
{ 
 void SaveMessage(string message); 
} 

И каждый класс, который который будет отвечать за сохранение логов пусть реализует данный интерфейс. Например для тех же файлов это может быть такой класс:

public class FileLogContainer: ILogContainer 
{ 
 public void SaveMessage(string message) 
 { 
  using (FileStream fileStream = new FileStream("log.txt", FileMode.Append, FileAccess.Write)) 
  { 
   StreamWriter writer = new StreamWriter(fileStream); writer.Write(message); 
  } 
 } 
} 

И тогда использование будет выглядеть следующим образом:

public class Logger 
{ 
 private ILogContainer logContainer; 
 public Logger(ILogContainer logContainer) 
 { 
  this.logContainer = logContainer; 
 } 
 public void LogMessage(string message) 
 { 
  logContainer. SaveMessage(message); 
 } 
}

После этого преобразования диаграмма зависимостей будет выглядеть:

image

Из диаграммы понятно почему этот подход называется Inversion of control, получается что зависимость от файловой системы была как бы развернута в обратную сторону.

Что нам дает этот подход? Помимо того, что теперь мы можем использовать любое хранилище логов, реализующее ILogContainer, полученный результат отлично поддается тестированию. Интерфейс ILogContainer дает точку в которй можно встроить mock object, с помощью которого можно правильно проверить работу класса Logger.