jmockit1 icon indicating copy to clipboard operation
jmockit1 copied to clipboard

Expectations for varargs methods don't fully allow mixing of literals+matchers

Open Vampire opened this issue 9 years ago • 1 comments

I spent the day to find out that my problem actually is the following JMockit bug:

If I have a method signature like the following

FacesMessage getMessage(Severity severity, String msgKey, Object... msgObjects)

then it does not work to write in an Expectations block

messageFactory.getMessage(SEVERITY_ERROR, "myKey", "a,23", anyString, anyString);

or

messageFactory.getMessage(SEVERITY_ERROR, anyString, "a,23", anyString, anyString);

or

messageFactory.getMessage(withArgThat(isA(Severity.class)), "myKey", "a,23", anyString, anyString);

But it does work if I write either

messageFactory.getMessage(withArgThat(isA(Severity.class)), withEqual("myKey"), withArgThat(is("a,23")), anyString, anyString);

or also if I write

messageFactory.getMessage(SEVERITY_ERROR, "myKey", "a,23", "foo", "bar");

The problem as far as I have seen through debugging JMockit code is, that no call to mockit.internal.expectations.transformation.ActiveInvocations#moveArgMatcher is generated during instrumentation, because of the matcher being "hidden" inside the Object[].

If no matchers are present at all like in my last example, mockit.internal.expectations.invocation.ArgumentValuesAndMatchersWithVarargs#isMatch just compares all values literally with the LenientEqualityMatcher, but if there is at least one matcher and it is in the var-args range, then the matchers array in ArgumentValuesAndMatchersWithVarargs cannot be used as is.

Taken my first example messageFactory.getMessage(SEVERITY_ERROR, "myKey", "a,23", anyString, anyString);, the matchers array would have the two anyString matchers at indices 0 and 1 instead of 3 and 4 as would be necessary for the current matching algorithm.

So I guess you either have to somehow make the moveArgMatcher calls get generated correctly for varargs method calls, or change the matching algorithm, or maybe transform non-special arguments to calls to withEquals() in the InvocationBlockModifier, like any* that are transformed to the respective method calls.

Vampire avatar Jun 13 '16 16:06 Vampire

Ok, it can be accepted as an enhancement request.

rliesenfeld avatar Jun 14 '16 15:06 rliesenfeld