3

In Test Driven Development, how do I make code bound to an ORM testable?

I am using a Micro-ORM (PetaPoco) and I have several methods that interact with the database like:

AddCustomer

UpdateRecord

etc.

I want to know how to write a test for these methods. I searched YouTube for videos on writing a test for DAL, but I didn't find any.

I want to know which method or class is testable and how to write a test before writing the code itself.

2
  • possible duplicate of Unit testing - Database coupled app
    – gnat
    Aug 31, 2012 at 9:38
  • @gnat: the question is similar, but not identical, since this is more specific to the existence of an ORM in this project.
    – Doc Brown
    Aug 31, 2012 at 13:10

3 Answers 3

9

Unit testing the code relying on your DAL should be straight-forward: use the repository pattern to decouple your business layer from your ORM. Provide your POCOs by an abstract repository, then you can either provide a "real" repository in production (which uses your ORM), or a mock repository for testing purposes which delivers just test-data POCOs without any DB access. Using an ORM which works with POCOs here has the advantage that you can easily create that objects in memory, without the need to rely on the ORM.

A different question is how to automatically test methods like "AddCustomer", assumed that this method contains only database or ORM related code. Having a short look into the PetaPoco documentation and source code, it seems to support just one database with in-memory capabilities: SqlLite. So I guess you could set up a lightweight SqlLite instance for your testdata and write your tests against this.

Theoretically, you could do this also with a full-blown relational DB system like Oracle or MS SQL server, but that option is often too slow and needs too much administrative overhead to be practical. If you want trying this route anyway, I suggest you have a look at DBUnit.NET, which supports this approach.

Whatever you will do, it may be a good idea to separate those two cases in your code: write (1) code pulling the needed objects from your DB into memory, and (2) separate code for doing the business logic, without any DB access. Surely you will need (3) code that manages (1) and (2)to make them work together, but (1) and (2) could be tested then more easily in isolation.

4

Look into Mock Objects and Dependency Injection.

Mock objects are a useful way to write unit tests for objects that act as mediators. Instead of calling the real domain objects, the tested object calls a mock domain object that merely asserts that the correct methods were called, with the expected parameters, in the correct order.

Dependency injection allows you to test a class in isolation, for example image a class with 5 private members, these objects are initilised in the constructor. Now unit testing of this class and its methods will also be running code concerned with other objects, this defeats the purpose of unit testing. Dependency injection allows the caller to pass in the 5 initialized objects and the constructor simply assigns them to the private members for example. This means I can pass in MockDB for example when unit testing, but for production code, pass in the real concrete DB object.

4

I've used PetaPoco in an application and what I ended up doing was just abstracting an interface for the Database object which just exposed the methods that I actually use (since there are 100s of them and I only actually needed 10-15).

This allowed me to provide mock implementations of that interface in unit tests and in my DI container I simply bound the Database object to the IDatabase interface.

I wouldn't bother implementing the repository pattern, abstracting an IDatabase interface will essentially become a generic repository anyway.

The resulting annoyance with this led me to create my own Micro-ORM (MicroLite) which is designed to allow ease of testing which you can find on GitHub and NuGet (note: at present it only supports MsSql).

2
  • +1. I guess for many cases that is a better approach than my sugestion to use SqlLite for testing purposes, though I see 2 drawbacks: you have to change the original PetaPoco code, and I guess you could not test if the SQL strings work correctly (at least not when you did not implement an SQL parser in your mock Database),
    – Doc Brown
    Aug 31, 2012 at 15:57
  • Yeah it allows your test to be a proper "unit" test, if you're relying on an sqllite database in a specific configuration it's more of an integration test. One of the other things we did with PetaPoco was ONLY use the sql class for queries which I also amended the code for so that it implemented equality properly. We then used static classes to return pre-defined queries which allowed us to test against specific queries or return particular results if we did multiple calls in the same method. (this is something I made sure that MicroLite did properly OOTB). Aug 31, 2012 at 16:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.