EasyMock Arguments

Posted by Mike Haller on Sunday, March 4. 2007 at 08:26 in Java
EasyMock Arguments

To mock objects, you need to know which methods are called with what parameters, so you can assert them.
For simple parameters like Strings or numbers, this is easy and you can record the value just by simply calling
the method:

IMyMock mock = myControl.createMock(IMyMock.class);
mock.doSomething("Foo"); // Point of interest
mock.replay();

// This will call IMyMock.doSomething("Bar")
// public void methodUnderTest() { myMock.doSomething("Bar"); }
classUnderTest.methodUnderTest();

// This will compare "Foo" with "Bar" and fail the test
mock.verify();


Here, mock.doSomething("Foo") will 1) record the method invocation of doSomething and 2) record the value "Foo"
for the first and only parameter.

For more complex parameter objects, or if you want to ease restrictions, you will probably want
to implement your own EasyMock IArgumentMatcher. In this case, the actual parameter within the unit test
source code does not matter and you can use null for them...
IMyMock mock = myControl.createMock(IMyMock.class);
EasyMock.reportMatcher(new MyOrMatcher("Foo","Bar","Baz"));
mock.doSomething(null); // Point of interest
mock.replay();

// This will call IMyMock.doSomething("Bar")
// public void methodUnderTest() { myMock.doSomething("Bar"); }
classUnderTest.methodUnderTest();

// This will compare "Foo" with "Bar" and fail the test
mock.verify();


The number of parameters and the number of registered matchers must be equal. There are some simple predefined
argument matchers like Any, NotNull, Equals etc.

It is also a good idea to create some Matchers which e.g. compare your value objects using reflection or some
Matcher for checking the contents of Collections. Sad that EasyMock does not contain richer Matchers.

Also, it can get quite annoying to compare method invocations like the following, as this leads to an Assert Error
description in the JUnit View which is ... rather long and not clearly arranged. It can take some time to even identify
which of the parameters actually failed the test.

Just compare the simple message with the more complex one:

java.lang.AssertionError: 
  Unexpected method call getNextDocNumber("FAPO", "EOP", "FOO", false, 2):
    getNextDocNumber("OPAF", "EOP", "FOO", false, 2): expected: 1, actual: 0


java.lang.AssertionError: 
  Unexpected method call store([com.foo.vo.SomeValueObjectData@b8bef7[
  set_id=null
  timecreated=null
  createdby=null
  timemodified=null
  modifiedby=null
  execution=null
  ourParty=null
  counterParty=null
  executionStatus=null
  pricedUnpricedDeb=null
  totalInventoryValue=null
  executionPrice=null
  bookedPrice=null
  siteId=null
  purchaseSaleIndicator=null
  ctrNo=null
  executionNumber=null
  accountId=null
  partySubtype=null
  accrualProce=null
  marketPriceEndOfMonth=null
  effectiveDate=null
  contractYear=null
  showExecutionPrice=null
  contractNumber=null
  commodityNumber=null
  accrualValue=null
  totalInventoryQuantity=null
  totalAllocatedQuantity=null
  fintransSubtype=null
  marketId=null
  premiumDiscount=null
  pricedQuantity=null
  pricedUSD=null
  netAmount=null
  netForeignAmount=null
  quotationalPeriodStart=null
  quotationalPeriodEnd=null
  pricingNumber=null
  executionId=null
  premiumDiscountPercentage=null
  premiumDiscountFXRate=null
  partType=null
]], "junit", 1):
    store([com.foo.vo.SomeValueObjectData@b7bgf3[
  set_id=null
  timecreated=null
  createdby=null
  timemodified=null
  modifiedby=null
  execution=null
  ourParty=null
  counterParty=null
  executionStatus=null
  pricedUnpricedDeb=null
  totalInventoryValue=null
  executionPrice=null
  bookedPrice=null
  siteId=null
  purchaseSaleIndicator=null
  ctrNo=null
  executionNumber=null
  accountId=null
  partySubtype=null
  accrualProce=null
  marketPriceEndOfMonth=null
  effectiveDate=null
  contractYear=null
  showExecutionPrice=null
  contractNumber=null
  commodityNumber=null
  accrualValue=null
  totalInventoryQuantity=null
  totalAllocatedQuantity=null
  fintransSubtype=null
  marketId=Test
  premiumDiscount=null
  pricedQuantity=null
  pricedUSD=null
  netAmount=null
  netForeignAmount=null
  quotationalPeriodStart=null
  quotationalPeriodEnd=null
  pricingNumber=null
  executionId=null
  premiumDiscountPercentage=null
  premiumDiscountFXRate=null
  partType=null
]], "junit", 1): expected: 1, actual: 0
	at org.easymock.internal.MockInvocationHandler
           .invoke(MockInvocationHandler.java:29)
	at org.easymock.internal.ObjectMethodsFilter
           .invoke(ObjectMethodsFilter.java:45)
	at $Proxy3.store(Unknown Source)


Did you find the difference? Never mind, with a little trick and a custom Matcher, you can get a
more helpful message:

java.lang.AssertionError: 
  Unexpected method call execute(...):
    execute(
pv_execstatus1: Expected 'O' but was 'F'
pv_execstatus2: Expected 'F' but was 'O'
): expected: 1, actual: 0
    store(, "junit", 1): expected: 1, actual: 0
	at org.easymock.internal.MockInvocationHandler 
           .invoke(MockInvocationHandler.java:29)
	at org.easymock.internal.ObjectMethodsFilter 
           .invoke(ObjectMethodsFilter.java:45)
	at $Proxy3.execute(Unknown Source)


Happy mocking




Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications
 
Submitted comments will be subject to moderation before being displayed.
 

About

My name is Mike Haller and I'm a software developer and architect at Bosch Software Innovations in Germany. I love programming, playing games and reading books. I like good food, making photos and learning and mentoring about the craftsmanship of commercial software development. Stack Overflow profile for mhaller

Quicksearch