When writing integration tests for business logic objects and data access objects, what makes the most sense to use for setup and validation? In my case, I'm using an ORM in the implementation of my data access interface that will be used in production, and I plumb that ORM implementation together with the business logic objects for integration testing. Given that the ORM implementation is tested separately using INSERT and SELECT statements for setup and validation, is it best for integration testing setup and validation to use the ORM implementation of the data access interface, to use the ORM directly, to use those INSERT and SELECT statements, or to do something else, edit: and why?

The ORM in this case is NHibernate, the ORM implementation of the data access interface is a simple pass-through to NHibernate's LINQ provider that also provides simple pagination and sorting mechanisms. I'm curious to know what you think, either generally or with this specific scenario.

edit: I'm not looking to know what DAO I should connect to the BL objects. That clearly should be the same DAO that will be used in production. The question is about the mechanism used to put data into the database to set up the test before the business logic function is tested. Presumably, the same mechanism would be used to poll the database after the business logic function is tested. Here's some very high-level pseudo-code to demonstrate what I mean:

    Foo fooBefore = GenerateFooForTesting();
    SomehowInsertIntoDatabase(foo); // What should be used here and why?

    // Plumb things together; actually done using IoC, not hard-coded.
    DaoFactory realDaoFactory = GetRealDaoFactory();
    BizFactory realBizFactory = GetRealBizFactory();
    realBizFactory.DaoFactory = realDaoFactory;

    BusinessLogicObject biz = realBizFactory.BuildBusinessLogicObject();

    Foo fooAfter = SomehowGetFooFromDatabase(fooBefore.Id); // Same question.

    Assert.AreEqual(5, fooAfter.SomethingThatShouldBeFiveAfterBusinessIsDone);

Okay, let's try this again :/ If your application normally will only work with data that has been inserted/retrieved using your ORM, then I'd test with that. If the application is going to have to work with data inserted by other means (legacy or converted data) then you should plan to insert some using raw SQL. The reason to use the ORM is to ensure that any changes you make will be properly tested "round trip": that is, if you add a column to a table you can make sure it gets properly populated when a record and created and properly retrieved when used. For legacy data, you need to ensure that your code works properly with data that hasn't been subjected to the checks and validation of your ORM layer. Be sure to use some bad data as well as good data, to ensure that you identify and handle invalid records properly.

  • Thanks for responding again, @TMN, and for being patient with the misunderstanding. I hadn't thought of the round-trip issue. The only downside I can think of to using the ORM for setup and validation would be that some ORM mapping mistakes might be hidden, but separately testing the ORM DAO should cover that. Between the round-trip issue and the ease of use with the ORM, I think that's the answer, certainly for scenarios where legacy data isn't involved. That round-trip issue is enough answer the question. Thanks! – Don 01001100 Feb 27 '12 at 23:15

Even though you are testing the data access layer directly, you may want to add some redundancy to your tests by also including it in an integration test and see how it collaborates with dependant code.

It depends on what you are trying to test really. For some tests you may want to fake the entire data access layer to keep your tests fast and have tighter control over your test setup.

  • A test of a business logic function that fakes the entire data layer would be a unit test, not an integration test. When you say to "includ[e] it in an integration test," can you clarify what you mean? My question presupposes that I'm writing an integration test. – Don 01001100 Feb 27 '12 at 13:38

If you're doing an integration test, then you're testing the interaction among different objects in different layers. Therefore, I'd use a setup as close as possible to the final system. You can often flush out edge cases this way (e.g., the ORM may throw an exception you hadn't anticipated when you present it with invalid data).

  • Thanks for your answer, @TMN. Please see my edit to the question and let me know if it's more clear. – Don 01001100 Feb 27 '12 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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