Unit Testing SQLite Repository generating No Such Table Error

Viewed 561

I have recently built a quiz application for Xamarin.Android, and want to dome some Unit Testing on the shared library.

I am using a repository pattern with the following files.

SQLiteMyAppRepository.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SQLite;

namespace MyApp.DataLayer
{
    public class MyAppRepository : IMyAppRepository
    {
        public static string DatabaseName = "MyApp.sqlite";

        private SQLiteConnection _dbConnection;

        public MyAppRepository()
        {
            string docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            string dbFilePath = Path.Combine(docFolder, DatabaseName);
            _dbConnection = new SQLiteConnection(dbFilePath);
        }

I have then created a new project to test some of these elements.

The primary issue I am having, is that when I try and run the test, I am getting the following exception:

MyApp.Tests.RepositoryTests.AddQuestion threw 
exception: 
SQLite.SQLiteException: no such table: Questions

I have been messing about with it for a few hours now and can't seem to find what is wrong, any help would be appreciated. I thought Mocking the repository would get around any issues like this.

1 Answers

The problem here is that you are trying to use a real database in the context of unit tests. One possible solution could be to introduce an additional level of abstraction and separate repository from context(database). This could enable you to properly mock dependencies, e.g.

public interface IMyAppContext
{
    IList<Question> GetAllQuestions();
    int AddQuestion(Question question);
    int UpdateQuestion(Question question);
    int DeleteQuestion(Question question);
}

where implementation could be something like this:

public class MyAppContext : IMyAppContext
{
    private readonly string _databaseName = "MyApp.sqlite";
    private readonly SQLiteConnection _dbConnection;

    public MyAppContext()
    {
        string docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        string dbFilePath = Path.Combine(docFolder, DatabaseName);
        _dbConnection = new SQLiteConnection(dbFilePath);
    }

    public int AddQuestion(Question question)
    {
        return _dbConnection.Insert(question);
    }

    ...
}

then inject this one to the repository...

public class MyAppRepository : IMyAppRepository
{
    private readonly IMyAppContext _context;

    public MyAppRepository(IMyAppContext context)
    {
        _context = context;
    }

    public int AddQuestion(Question question)
    {
        return _context.Insert(question);
    }

    ...
}

Now, after you have done this setup of the unit test should be for example,

[TestMethod]
public void AddQuestion()
{
    // Arrange
    var contextMock = new Mock<IMyAppContext>();
    contextMock.Setup(r => r.AddQuestion(It.IsAny<Question>())).Returns(1);
    var sut = new SqLiteAbcdRepository(contextMock.Object);

    // Act
    var id = sut.AddQuestion(new Question());

    // Assert
    Assert.AreEqual(1, id);
}
Related