There is a problem within the CommonMockStatement
class. I have created a MockPreparedStatement that
extends the CommonMockPreparedStatement (included
below).
Within this class I have implemented counters for the
addBatch and clearBatch calls. The counters work
correctly, but if the count is not correct, I receive a very
misleading assertion failure (also shown below).
Notice that the message indicates the incorrect number
of "executeCalls" was received. I thought that there
must be some user error in my MockPreparedStatement
until I saw the same behavior and exact same message
when the incorrect number of ExpectedSetParameters
was hit. I haven't modified that code.
To reproduce, create a MockPreparedStatement and call
the addExpectedSetParameters method twice, but run it
on code that actually tries to set the statements
parameters 3 or more times. You will get the following
error. This error is very misleading and could result in
hours of unnecessary debugging time for the
unsuspecting user.
*********** Assertion Failure ***********
junit.framework.AssertionFailedError:
CommonMockStatement.executeCalls did not receive
the expected Count.
Expected: 1
Received: 0
at junit.framework.Assert.fail(Assert.java:51)
at
com.mockobjects.AbstractExpectation.assertEquals
(AbstractExpectation.java:39)
at
com.mockobjects.AbstractExpectation.assertEquals
(AbstractExpectation.java:17)
at
com.mockobjects.ExpectationCounter.verify
(ExpectationCounter.java:37)
at com.mockobjects.util.Verifier.verifyField
(Verifier.java:77)
at
com.mockobjects.util.Verifier.verifyFieldsForClass
(Verifier.java:63)
at
com.mockobjects.util.Verifier.verifyFieldsForClass
(Verifier.java:57)
at
com.mockobjects.util.Verifier.verifyFieldsForClass
(Verifier.java:57)
at com.mockobjects.util.Verifier.verifyObject
(Verifier.java:49)
at com.mockobjects.MockObject.verify
(MockObject.java:44)
at
com.tivoli.tec.eds.AddRemarksWorkRequestUnitTest.tea
rDown(AddRemarksWorkRequestUnitTest.java:802)
at junit.framework.TestCase.runBare
(TestCase.java:143)
at junit.framework.TestResult$1.protect
(TestResult.java:106)
at junit.framework.TestResult.runProtected
(TestResult.java:124)
at junit.framework.TestResult.run
(TestResult.java:109)
at junit.framework.TestCase.run
(TestCase.java:131)
at junit.framework.TestSuite.runTest
(TestSuite.java:173)
at junit.framework.TestSuite.run
(TestSuite.java:168)
at junit.framework.TestSuite.runTest
(TestSuite.java:173)
at junit.framework.TestSuite.run
(TestSuite.java:168)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.ru
nTests(RemoteTestRunner.java:329)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.ru
n(RemoteTestRunner.java:218)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.m
ain(RemoteTestRunner.java:151)
*********** MockPreparedStatement***********
import java.sql.SQLException;
import com.mockobjects.ExpectationCounter;
import
com.mockobjects.sql.CommonMockPreparedStatement;
public class MockPreparedStatement extends
CommonMockPreparedStatement
{
/**
* Return values for executeBatch
*/
private int[] myBatchCount = new int[] { 0 };
/**
* addBatch <code>ExpectationCounter</code>
*/
private ExpectationCounter myAddBatchCalls =
new ExpectationCounter
("MockPreparedStatement.addBatch");
/**
* clearBatch <code>ExpectationCounter</code>
*/
private ExpectationCounter myClearBatchCalls =
new ExpectationCounter
("MockPreparedStatement.clearBatch");
/**
* Increments the number of times that addBatch() is
called.
*/
public void addBatch() throws SQLException
{
myAddBatchCalls.inc();
} // end addBatch method
/**
* Increments the number of times that clearBatch() is
called.
*/
public void clearBatch() throws SQLException
{
myClearBatchCalls.inc();
} // end clearBatch method
/**
* Returns executeBatch(String) with an empty String.
*/
public int[] executeBatch() throws SQLException
{
return executeBatch("");
} // end executeBatch method
/**
* Simulates the executeBatch call.
*
* Sets the actual SQL string received by the method
for later testing.
* Calls innerExecute() to increment the executeCount
and throw an
* exception if necessary. Returns the appropriate
established batch count.
*/
public int[] executeBatch(String sql) throws
SQLException
{
myQueryString.setActual(sql);
innerExecute();
return myBatchCount;
} // end executeBatch method
/**
* Sets the <code>ExpectationCounter</code> for
calls to clearBatch().
*/
public void setExpectedClearBatchCalls(int callCount)
{
myClearBatchCalls.setExpected(callCount);
} // end setExpectedClearBatchCalls method
/**
* Sets the <code>ExpectationCounter</code> for
calls to addBatch().
*/
public void setExpectedAddBatchCalls(int callCount)
{
myAddBatchCalls.setExpected(callCount);
} // end setExpectedAddBatchCalls method
/**
* Sets the return values for calls to executeBatch.
*/
public void setupBatchCount(int[] batchCount)
{
myBatchCount = batchCount;
} // end setupBatchCount method
} // end MockPreparedStatement class
Logged In: YES
user_id=123464
Very odd. The only thing I can think of is that the
expectation is getting reset somewhere. Could you
upload an example of one of your tests?
Logged In: YES
user_id=652617
I am unable to send the actual code that is being tested or
the test cases used to create them for confidentiality
reasons. However, I have created a simple class and
accompanying test case that I will send shortly (with the
next comment).
I have discovered (I think) why the executeCalls count is
wrong in the situation where the incorrect number of
parameters is set. I think that the test case fails
immediately, then the number of calls to execute count is
never actually set. In addition, the verify method probably
reports on this property before reporting on others, so it
comes up as the primary failure, even though something else
actually caused the error.
Just a thought and if that is the case, then I can live with
that one. However, it may be a good idea to move the count
checks to be the very last thing that happens when verify is
called. That way, more descriptive, detailed error messages
will be reported first.
Again, this is just a thought. I'll send the example code
shortly.
ZIP containing simple class, test class, and modified MockPreparedStatement
Logged In: YES
user_id=652617
OK...I'm including the simple class and test class here along with my modified MockPreparedStatement that has
the add/clear batch methods implemented with counters. I now believe that the errors have everything to do with
the order in which the mock objects are "verified". I have found a way to get the correct error message...if the test
case sets the expected number of calls to add/clearBatch to something greater than what it actually receives and
nothing else is wrong, then the error message is correct. If, however, you change only the number of calls to
add/clearBatch that are expected to something less than what actually gets called, then "other" errors get caught
first.
This can be very misleading. I have included the files with this comment. Please try different combinations of
values and statements being commented out to see all the different types of messages you will get. The test
class currently has 5 test cases (only 1 of which will pass). I tried to demonstrate several different scenarios and
error messages.
Suggestion: Another approach to this problem would be to comment the order in which these errors are reported.
However, I think that the problem is a little deeper than that. If you go into the add/clearBatch test methods and
uncomment ALL lines and run it once with different values for the number of expected calls, you should still get the
same error as long as nothing else has been changed. This, however, won't happen.
Thanks!