i have began unit testing not long ago so that as switched out used to do more regression testing than unit testing because i additionally incorporated my database layer thus visiting the database verytime.

So, implemented Oneness to inject an imitation database layer, however i obviously wish to store some data, and also the primary opinion was: "create an in-memory database"

But what's that / how do you implement that?

Primary real question is: i believe i must fake the database layer, but does not which make me produce a 'simple database' myself or: how do i make it simple and never repairing Sql Server only for my unit tests :)

In the finish of the question i'll give a reason from the situation i acquired in around the project i simply began on, and i'm wondering if the was what you want.

Michel

Unique circumstances i have seen only at that client is the fact that testdata is found in XML files, and there's a 'fake' database layer that connects all of the xml files together. For that real database we are while using entity framework, which works quite simple. And today, within the 'fake' layer, i've top create all type of classes to load, save, persist etc. the information. It may sound strange that there's a lot operate in the fake layer, and thus little within the real layer.

I really hope all of this is sensible :)

EDIT: and so i know i must produce a separate database layer for my unit test, but how do you implement it?

Define an interface for the data access layer and also have (a minimum of) two implementations from it:

  • The actual database provider, that will consequently run queries with an SQL database, etc.
  • An in-memory test provider, which may be prepopulated with test data included in each unit test.

The benefit of this would be that the modules utilizing the data provider don't need to if the database may be the real one or even the test one, and therefore a lot of real code is going to be examined. The exam database could be simple (like simple collections of objects) or complex (custom structures with indexes). It is also a mocked implementation which will assert it's being known as properly included in the test.

Furthermore, should you ever have to support another data storage method (or different SQL database), you need to simply write another implementation that adjusts towards the interface, and may be reassured that no calling code will have to be reworked.

This method is simplest if you are planning for this from (or near) the beginning, so I am unsure how easy it will likely be to use for your situation.

What it really might seem like

If you are just loading and saving objects by id, you'll be able to come with an interface and implementations like (in Java-esque pseudo-code I'm not sure much about asp.internet):

interface WidgetDatabase {
    Widget loadWidget(int id);
    saveWidget(Widget w);
    deleteWidget(int id);
}

class SqlWidgetDatabase extends WidgetDatabase {
    Connection conn;

    // connect to database server of choice
    SqlWidgetDatabase(String connectionString) { conn = new Connection(connectionString); }

    Widget loadWidget(int id) {
        conn.executeQuery("SELECT * FROM widgets WHERE id = " + id);
        Widget w = conn.fetchOne();
        return w;
    }

    // more methods that run simple sql queries...
}

class MemeoryWidgetDatabase extends WidgetDatabase {
    Set widgets;

    MemoryWidgetDatabase() { widgets = new Set(); }

    Widget loadWidget(int id) {
        for (Widget w: widgets)
            if (w.getId() == id)
                return w;
        return null;
    }

    // more methods that find/add/delete a widget in the "widgets" set...
}

If you want to run more other queries (for example batch chooses according to more complicated criteria), you can include techniques to get this done towards the interface.

Likewise for complex updates. Transaction support can be done for that real database implementation. I am unsure how easy it's to construct an in-memory db that's able to supplying proper transaction support. To check it you'd need "open" several "connections" towards the same data set, and also to only apply updates to that particular shared dataset whenever a transaction is committed.

i made use of Sqlite for unit test as fake DB