Reputation: 15042
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
Upvotes: 1
Views: 8290
Reputation: 16380
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);
}
Upvotes: 1
Reputation: 32949
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.
Upvotes: 2