Did a bit of unit test hacking while on the plane last night. Just checked in some pretty good early results. We are still bound by JUnit 3 lifecycle simplicity and have to use static singletons, still I was able to build a little framework for dependency injection into the test cases, with access to the new DI Cayenne stack. Underneath that is an old CayenneResources singleton that loads DB connection, generates the schema, etc...

Still the unit test "frontend" is now drastically different (see e.g. DataContextEJBQLConditionsTest, one of the few tests that I switched). Tests extending DICase (or its subclass - ServerCase) can use @Inject annotations to get access to the interesting parts of the stack being tested (in 90% of cases that I converted so far this would be ObjectContext and DBHelper) in a clean manner that does not obfuscate the test purpose. I also replaced Spring/XML data sets with DBHelper. So a typical DB-aware test case may look like DataContextEJBQLConditionsTest:

@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
public class DataContextEJBQLConditionsTest extends ServerCase {

    @Inject
    protected ObjectContext context;

    @Inject
    protected DBHelper dbHelper;

    protected TableHelper tArtist;

    @Override
    protected void setUpAfterInjection() throws Exception {
        dbHelper.deleteAll("PAINTING_INFO");
        ...
        tArtist = new TableHelper(dbHelper, "ARTIST");
        tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
        ...
    }

    protected void createDataSetXYZ() throws Exception {
        tArtist.insert(33001, "B");
        tArtist.insert(33002, "A");
        tArtist.insert(33003, "D");

        tPainting.insert(33009, 33001, "X", 5000);
        tPainting.insert(33010, 33001, "Y", 5000);
        tPainting.insert(33011, 33002, "Z", 5000);
    }

    public void testSomething() throws Exception {
        createDataSetXYZ();

        // normal unit test goes here
        ...
    }

It is much cleaner than what we had before at the unit test level at the expense of a few trivial DI providers in the DI backend.

In general I feel like the Cayenne DI container is a cool little piece of technology that will take us pretty far in many areas of the framework. It is still only 36K in size and has simplicity as its main design paradigm. The only major feature that it is missing compared to the other guys is method interception, and we can add that down the road if we feel compelled to have it for Cayenne uses.

Cheers,
Andrus

Reply via email to