Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override Mockito toString test output

I have written a custom Hamcrest Matcher<Double> to use with Mockito.doubleThat.

I want to "override the toString()" method, so to speak, so that if there's a failure, the error is more verbose. Here's the JUnit failure trace:

Argument(s) are different! Wanted:
dependedOnComponent.method(
    <Double matcher>
);
-> at my.domain.TestClass.testMethod(TestClass.java:123)
Actual invocation has different arguments:
dependedOnComponent.method(
    123.45,
);
-> at my.domain.SystemUnderTest.callingMethod(SystemUnderTest.java:456)

As you can see, it prints <Double matcher>. Is it possible to override that message? Instead, I would like to see, as an example:

Argument(s) are different! Wanted:
dependedOnComponent.method(
    120 < matcher < 121
);

But a different instantiantion of my matcher class might be:

Argument(s) are different! Wanted:
dependedOnComponent.method(
    1 < matcher < 200
);

I don't need to know how to write the code to generate the numbers or the syntax, I just need to know WHERE to put it.

like image 839
durron597 Avatar asked May 23 '14 14:05

durron597


2 Answers

So I was doing something silly; I was reading the Javadoc for Matcher when I really should have been looking at the Javadoc for ArgumentMatcher.

Once I realized my mistake, it's easy; just override the describeTo method defined in that interface, e.g.

@Override
public void describeTo(Description description) {
    description.appendText(String.valueOf(expected));
    description.appendText(" ± ");
    description.appendText(String.valueOf(delta));
}
like image 72
durron597 Avatar answered Sep 24 '22 01:09

durron597


Try the following:

@RunWith(MockitoJUnitRunner.class)
public class SOTest {

    public interface Foo {
        void doSomething(double d);
    }

    @Test
    public void sillyTest() {

        Foo foo = mock(Foo.class);
        foo.doSomething(1);
        verify(foo).doSomething(Mockito.doubleThat(new TestMatcher(2)));
    }

    public class TestMatcher extends CustomMatcher<Double> {

        private final double expected;

        public TestMatcher(double expected) {
            super(Double.toString(expected));
            this.expected = expected;
        }

        @Override
        public boolean matches(Object item) {
            return item instanceof Double && ((Double) item).equals(expected);
        }
    }
}

Output:

Argument(s) are different! Wanted:
foo.doSomething(2.0);
-> at SOTest.sillyTest(SOTest.java:23)
Actual invocation has different arguments:
foo.doSomething(1.0);
-> at SOTest.sillyTest(SOTest.java:22)
like image 38
Duncan Jones Avatar answered Sep 22 '22 01:09

Duncan Jones