views:

27

answers:

1

At our comapny, we have a service layer which takes in a some request XML, accesses various Stored Procecdures (SP's) via JDBC, processes the data and responds with some response XML. Lately people have begun to adopt MockRunner in their JUnit tests to mock the responses from the SP's. The code to setup the mocked responses from the SP's using MockRunner looks awful (this is the first random test class I opened):

    MockConnection connection = new MockConnection();
    MockContextFactory.setAsInitial();
    InitialContext context = new InitialContext();
    context.rebind(READ_PAYMENT_DATA_SOURCE, getDS());
    getDS().setupConnection(connection);
    m_csStatementHandler = connection.getCallableStatementResultSetHandler();
    m_csStatementHandler.clearResultSets();
    m_csStatementHandler.clearCallableStatements();
    m_csStatementHandler.setExactMatch(false);
 m_csStatementHandler.prepareReturnsResultSet(READ_PAYMENT, true);
    m_csStatementHandler.setExactMatch(false);
    m_csStatementHandler.setExactMatchParameter(false);
    Map parameterMap = new HashMap();
    parameterMap.put(new Integer(1), null);
    parameterMap.put(new Integer(2), null);
    parameterMap.put(new Integer(3), null);
    parameterMap.put(new Integer(4), null);
    m_csStatementHandler.prepareOutParameter(READ_PAYMENT, parameterMap);
    //Set up the cursor of applications for return.
    MockResultSet resultApps = m_csStatementHandler.createResultSet();  

    resultApps.addRow(getPaymentSchedule("E", "Monthly", new Short("1"),null,null,null,null,null,null,null));
    resultApps.addRow(getPaymentSchedule("A", "Weekly", new Short("1"),null,null,null,null,null,null,null));
    resultApps.addRow(getPaymentSchedule("R", "Yearly", new Short("1"),null,null,null,null,null,null,null));
    resultApps.addRow(getPaymentSchedule("S", "Weekly", new Short("1"),null,null,null,null,null,null,null));
    resultApps.addRow(getPaymentSchedule("W", "Monthly", new Short("1"),null,null,null,null,null,null,null));

    MockResultSet[] results = new MockResultSet[1];
    results[0] = resultApps;
    m_csStatementHandler.prepareResultSet(READ_PAYMENT, resultApps);   

The code above is awful for many reasons, but it does clearly show the complexity and overhead of setting up a response from the stored procedures.

To date I have been using hand rolled dependency injection instead to inject the class that actually calls the Stored Procedure. All I have to do is create a mock SP caller class (responsible for the actual execution of the SP) and set my desired response data. I'm very happy with this technique and its much simplier than the above as its data focused rather than worrying about implementation details. But my question is, when would you want to use MockRunner? It seems overkill for unit tests, so am I guessing its more for integration or system testing? And even then, it still strikes me as easier to use a DI framework to swap out the SP caller class then to setup all the code above for every stored procedure call. Please enlighten! Thanks

+1  A: 

Ultimately you're looking into the philosophy behind mocking in general. I'll give you my two cents, but I'd also refer to you any major mocking library, which is likely to provide good justification for their own existence. Take Mockito, for example.

The testing/mocking community often distinguishes between what you're hand-rolling, which is usually called a "stub" (a static, hand-written class) versus a "mock" (a dynamic, runtime-generated class).

The benefits of mocking are pretty big in comparison to just stubbing. Many testers chafe at the idea of going off to write implementations of interfaces and/or subclass concrete classes just for the purpose of testing. To do so often requires the implementation of ALL methods of said class/interface, even when you just want to test a specific method.

Mocking lets you get around that problem by defining just the methods to which you want to give behavior, and that's powerful. In addition, mocking allows you to change behavior from one test to the next. To do that with stubbing, you'd have to write an entirely new stub class.

The syntax varies a little from mocking library to library. Some you may find more readable than others. My current favorite is Mockito, hence the earlier reference, but they evolve over time. It might be worth determining why your organization is using the mocking suite that it is and whether another might still meet your needs as well as being more readable.

Hopefully your test-writers are pulling common behavior into test-setup methods (like JUnit's @Before) so you don't have to keep seeing mock-creation and common initialization all over the place.

RonU
Thanks for this. I am familiar with Mockito which I like a lot.
Chris Knight