简体   繁体   中英

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

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.

Apart from the line with returns(any) in a redundant expectation block, I don't see any problem in the example test code fragments. It would help to see a complete example test which throws the error, though.

In any case, the following example test should also work:

@Test
public void createAPaymentStub(@Mocked final PaymentStubDAO mockPaymentStubDAO)
{
    // Executed somewhere inside the code under test:
    PaymentStub stub = new PaymentStub();
    stub.setDaysJuror(1);
    mockPaymentStubDAO.create(stub);

    new Verifications() {{
        mockPaymentStubDAO.create(with(new Delegate<PaymentStub>() {
           void validate(PaymentStub stub) {
               assertEquals(1, (int)stub.getDaysJuror());
           }
        }));
    }};
}

(The any / anyXyz fields are only meant to be used as argument matchers in recorded/verified expectations, while returns(...) is only meant for recording return values of non- void methods.)

Alternatively, you can use the Mockups API, which for this case is a bit simpler:

@Test
public void createAPaymentStub()
{
    PaymentStubDAO mockDAO = new MockUp<PaymentStubDAO>() {
        @Mock
        void create(PaymentStub stub) {
           assertEquals(1, (int)stub.getDaysJuror());
        }
    }.getMockInstance();

    // Executed somewhere inside the code under test:
    PaymentStub stub = new PaymentStub();
    stub.setDaysJuror(1);
    mockDAO.create(stub);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM