Search code examples
javajmockit

How to mock create in jmockit


I am new to jmockit, although the framework is currently in use slightly inside our application.

I am attempting to mock out my DAOs for my services layer. I understand how to use returns on my expectations to return my objects for my read methods, but I want to capture the objects created using the create methods so that I can test them.

How do I do this?

for instance, DAO contains:

public void create(Person person){
    //code to create person here.
}

I want to mock it up so that I capture the person coming into this method so I can interrogate later in my tests.

Based on feedback, I made a test using the following...

@Mocked @NonStrict
private PaymentStubDAO mockPaymentStubDAO;

...

new Expectations() {
    {
    mockPaymentStubDAO.create((PaymentStub) any);
    returns(any);
    }
};

...

//set up the verifications
new Verifications() {{
  mockPaymentStubDAO.create((PaymentStub) any);
  forEachInvocation = new Object() {
     @SuppressWarnings("unused")
    void validate(PaymentStub stub) {
         assertEquals(1, (int)stub.getDaysJuror());
     }
  };

}};

And when I run it, I get the following error on the line with new Verifications():

java.lang.AssertionError: Missing 1 invocation to:
Object com.acs.gs.juror.dao.accounting.PaymentStubDAO#create(Object)
with arguments: null
on mock instance: $Impl_PaymentStubDAO@424f8ad5
    at com.acs.gs.juror.manager.accounting.impl.AccountingManagerImplTest$2.<init>(AccountingManagerImplTest.java:1925)
    at com.acs.gs.juror.manager.accounting.impl.AccountingManagerImplTest.testPayOverUnderLimit(AccountingManagerImplTest.java:1924)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: Missing invocations
    at com.acs.gs.juror.manager.accounting.impl.AccountingManagerImplTest$1.<init>(AccountingManagerImplTest.java:1859)
    at com.acs.gs.juror.manager.accounting.impl.AccountingManagerImplTest.testPayOverUnderLimit(AccountingManagerImplTest.java:1845)
    ... 12 more

Solution

  • Per the documentation:

     @Test
    public void verifyExpectationWithArgumentValidatorForEachInvocation(
         final Collaborator  mock)
    {
      // Inside tested code:
      new Collaborator().doSomething(true, new int[2], "test");
    
      new Verifications() {{
         mock.doSomething(anyBoolean, null, null);
         forEachInvocation = new Object()
         {
            void validate(Boolean b, int[] i, String s)
            {
               assertTrue(b);
               assertEquals(2, i.length);
               assertEquals("test", s);
            }
         };
      }};
    

    }

    Found at JMockit Docs

    FYI, as I mentioned in your previous question Mockito makes this a lot easier in my opinion. Ask yourself if you are really locked down to JMockit.