Sid
Sid

Reputation: 440

Wierd mockito InvalidUseOfMatchersException when calling mock from some method

import org.mockito.Mockito;

public class Scratch2 {
public static class Foo {
}

public interface Custom {
    public void someMethod(String arg1, String arg2, String arg3,
            String arg4);
}

public static class SomeClass {

    private final Custom custom;

    public SomeClass(Custom c) {
        this.custom = c;
    }

    public boolean run(Foo someFoo) {
        custom.someMethod("Dummy", "Dummy", "Dummy", "Dummy");
        return false;
    }
}

public static void callSomeMethod(Custom custom) {
    custom.someMethod("Dummy", "Dummy", "Dummy", "Dummy");
}

public static void main(String[] args) {
    Custom mock = Mockito.mock(Custom.class);
    SomeClass c = new SomeClass(mock);
    callSomeMethod(Mockito.mock(Custom.class));
    c.run(Mockito.any(Foo.class));

}
}

If we mock the custom interface and call someMethod on it directly there is no problem. But using the run() gives the following error:

==========

Exception in thread "main" org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers! 4 matchers expected, 1 recorded: -> at com.knewton.scratch.Scratch2.main(Scratch2.java:37)

This exception may occur if matchers are combined with raw values: //incorrect: someMethod(anyObject(), "raw String"); When using matchers, all arguments have to be provided by matchers. For example: //correct: someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.

at com.knewton.scratch.Scratch2$SomeClass.run(Scratch2.java:24) at com.knewton.scratch.Scratch2.main(Scratch2.java:37)

===========

This is on mockito 1.9.5

Upvotes: 1

Views: 2802

Answers (2)

Alfonso
Alfonso

Reputation: 8492

Your use of the matcher in this case is not correct. What happens is that mockito will record this matcher to use in a future call to a mocked method, which in your case happens here:

public boolean run(Foo someFoo) {
    custom.someMethod("Dummy", "Dummy", "Dummy", "Dummy"); // <- call on mock
    return false;
}

mockito counts your use of Mockito.any(Foo.class) for this method and now rightly complains that you only provided one matcher, but in fact, since the method requires 4 parameters, you need to pass 4 matchers.

Instead of passing a matcher to your run() method you should instead either pass a real instance (as you do in your own answer), or if that object is hard to instantiate and you don't need it anyway, you can replace it by a mock:

public static void main(String[] args) {
    Custom mock = Mockito.mock(Custom.class);
    SomeClass c = new SomeClass(mock);
    c.run(Mockito.mock(Foo.class));
}

Upvotes: 1

Sid
Sid

Reputation: 440

So here is how I worked around it and its weird. Its definitely a bug.

    import org.mockito.Mockito;

    public class Scratch2 {
        public static class Foo {
        }

        public interface Custom {
            public void someMethod(String arg1, String arg2, String arg3,
                    String arg4);
        }

        public static class SomeClass {

            private final Custom custom;

            public SomeClass(Custom c) {
                this.custom = c;
            }

            public boolean run(Foo serviceDiscoveryConfig) {
                custom.someMethod("Dummy", "Dummy", "Dummy", "Dummy");
                return false;
            }
        }

        public static void main(String[] args) {
            Custom mock = Mockito.mock(Custom.class);
            SomeClass c = new SomeClass(mock);
            Foo foo = new Foo();// HAD TO MAKE A NEW OBJECT HERE!
            c.run(foo);
        }
    }

Upvotes: 0

Related Questions