The Repository pattern is a technique used to manage the persistence of objects to a relational database, while decoupling the domain objects from the persistence technology. An Object-Relational Mapper (ORM), such as NHibernate can be used to map objects to database tables.
There is not usually much logic to test in a repository class, except for the interaction with the ORM, so there is often little need for testing the repository class independently from the database. What we really care about is the integration with the underlying data store. We can write integration tests to ensure this interaction is working correctly.
When executing tests against a database, tables can become cluttered with test data, often causing conflicts with subsequent tests. One solution is to run a SQL script before the tests are run which resets the database. However, this means we have to maintain a separate database script. If the database schema changes, we have to make sure this script is updated, or the tests might fail.
The open-source CodeCampServer project offers a great solution to testing NHibernate repository classes against a database. This involves recreating the test database schema from the NHibernate mapping files before each test is run.
Creating the database schema
The NHibernate SchemaExport method can be used to generate database schema from the .hbm mapping files. This allows us to create the test database schema without the need to maintain a separate database script.
By placing this code in the test fixture SetUp method, the database schema is recreated before each test is run, ensuring there are no conflicts with data from previous tests.
A base class can be created to provide this functionality for any test fixture that derives from it.
To create the database schema, the data type must be specified for each primary key column mapping. NHibernate derives the SQL types for the other columns from the .NET type associated with each mapping. The generated schema may not exactly match the real database schema, but it is sufficient enough to test the object persistence.
It is preferable to run the tests against a local database, as this will help increase test performance and prevent conflicts with other developers running tests against a shared database.
Writing the tests
Here I am using an example of a repository integration test from the CodeCampServer project.
The PresonRespositoryTester class derives from DatabaseTesterBase, which provides the schema export functionality.
Any required test data is created using the NHibernate session directly. The test data objects are saved to the session and flushed to the database.
Next, the SUT (System Under Test) is exercised by calling the Save method on the repository.
Finally, the results are loaded back from the database and verified against a set of expectations.
These tests will run much slower than standard unit tests, but that’s fine, as integration tests should be run less often than unit tests.
By generating the database schema before each test is run, we can ensure each test executes against a known set of data and is not affected by data generated from other tests. This helps us to create reliable and consistent data access integration tests.