C# – Best Practices for Generic Repository Unit Testing

crepository-patternunit testing

How can I unit test my generic repository?

Unit testing code:

[TestClass]
public class UnitTestLanguage
{
    private IUnityContainer _unityContainer;
    private IUnitOfWork _uow;
    private IGenericRepository<Language> _languageRepository;

    [TestInitialize]
    public void TestInitialize()
    {
        _unityContainer = new UnityContainer();
        _uow = _unityContainer.Resolve<UnitOfWork>();
        _languageRepository = _uow.GetRepository<Language>();
    }

    [TestCleanup]
    public void TestCleanup()
    {
        _uow = null;
        _unityContainer = null;
        _languageRepository = null;
    }


    [TestMethod]
    public void TestMethodInsertLanguage()
    {
        var newLanguage = new Language { Name = "test_language" };
        _languageRepository.Insert(newLanguage);
        var insertedRowCount = _uow.SaveChanges();

        var insertedLanguage = _languageRepository.Find(newLanguage.Id);
        _languageRepository.Delete(newLanguage);
        var deletedRowCount = _uow.SaveChanges();

        Assert.AreEqual(insertedLanguage.Name, newLanguage.Name);
        Assert.AreEqual(1, insertedRowCount);
        Assert.AreEqual(1, deletedRowCount);
    }
}

I use something like above. But I dont know this is the correct way to test repository. I cant find useful tutorial/article. How should be unit testing with generic repository CRUD operations?

Best Answer

Apart from Luc's suggestion to test one functionality per test (method), I would suggest not to use unity for setting up the unit under test. Strictly speaking, this is no unit test anymore, because it tests both your repository and the configuration of unity.

This might not be a problem for now, but it can easily become one in the future. Consider, for example, the situation that someone extends you language repository by some online-lookup functionality. The respective request interface would probably be retrieved though DI. In consequence, your tests may suddenly start to fail at random, because of occasional connection timeouts.

From my experience I prefer to be strict about dependencies in unit tests, i.e., every input is replaced manually by a respective mock. This is the only way you can make sure that a test failure actually relates to some problem with the unit (or the expectations your tests express).