3
votes

I am trying to use the allowing method to fix the return value of a method on one of my mocked objects. I have the following method on a mocked object jdbc which I want to allow for:

List<T> query(String sql, RowMapper<T> rowMapper)

I am using with(any(RowMapper.class)) because I don't really care which RowMapper is used - I just want to make sure that when it calls query with that SQL it returns a List with "bob".

import java.util.Arrays;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.auto.Mock;
import org.jmock.integration.junit4.JUnitRuleMockery;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcOperations;

public class GetCustomersPhaseTest
{
    @Rule
    public final JUnitRuleMockery mockery = new JUnitRuleMockery();

    @Mock
    private SimpleJdbcOperations jdbc;

    @Mock
    private EventPublisher events;

    @Mock
    private Context context;

    private GetCustomersPhase phase;

    @Before
    public void setup()
    {
        phase = new GetCustomersPhase(jdbc, events);
    }

    @Test
    public void testGetCustomers()
    {
        mockery.checking(new Expectations() {
            {
                allowing(jdbc).query(with(equal("SELECT Name FROM Customers")), with(any(RowMapper.class)));
                will(returnValue(Arrays.asList("Bob")));
            }
        });

        phase.execute(context);
    }
}

However this gives me,

java.lang.IllegalArgumentException: not all parameters were given explicit matchers: either all parameters must be specified by matchers or all must be specified by values, you cannot mix matchers and values
    at org.jmock.internal.InvocationExpectationBuilder.checkParameterMatcherCount(InvocationExpectationBuilder.java:98)
    at org.jmock.internal.InvocationExpectationBuilder.createExpectationFrom(InvocationExpectationBuilder.java:91)
    at org.jmock.internal.InvocationToExpectationTranslator.invoke(InvocationToExpectationTranslator.java:19)
    at org.jmock.internal.FakeObjectMethods.invoke(FakeObjectMethods.java:38)
    at org.jmock.lib.JavaReflectionImposteriser$1.invoke(JavaReflectionImposteriser.java:33)
    at $Proxy10.query(Unknown Source)
    at com.thecat.test.GetCustomersPhaseTest$1.<init>(GetCustomersPhaseTest.java:45)
    at com.thecat.test.GetCustomersPhaseTest.testGetCustomers(GetCustomersPhaseTest.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.jmock.integration.junit4.JUnitRuleMockery$1.evaluate(JUnitRuleMockery.java:49)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    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)

I looked at this question and tried to solve the issue but I still cant get it work.

2
Looks OK to me. Are you sure you've identified the correct expectation that's failing?Duncan Jones
Ive provided some more code, I was using a Hamcrest equalTo method. I am now using the equal method from Expectations.The Cat
figured it out, silly varargs!The Cat

2 Answers

2
votes

SimpleJdbcOperations#query takes an Object... as the final parameter. The error occurs because this is not accounted for by a with method, I think its because this compiles down to passing an empty array to this method which is not accounted for.

It works if you use,

allowing(jdbc).query(with(equal("SELECT Name FROM Customers")), with(any(RowMapper.class)), with(equal(new Object[0])));
will(returnValue(Arrays.asList("Bob")));
0
votes

Quick first check, can you make sure you're importing the right with(), equalTo() and any() methods? sometimes there are similar methods from other packages.