false-positive java.lang.IllegalArgumentException: Attempted to record expectation on unmockable method #340

Closed
Vampire opened this Issue Sep 22, 2016 · 4 comments

Projects

None yet

2 participants

@Vampire
Vampire commented Sep 22, 2016 edited

Having the attached example project test.zip (unzip and run gradlew test -i), you get an error Attempted to record expectation on unmockable method.

The String @Injectable is necessary to satisfy the Logger constructor argument. But as far as I understand the Injectable JavaDoc, no other instances of String should be affected in any way. Yet this error occurs while actually no expectation for this method is recorded, its return value is just used as argument matcher.

Workaround: Do the getBytes() call before the Expectations block

@rliesenfeld rliesenfeld added the other label Sep 22, 2016
@rliesenfeld
Member

String is not being mocked at all. It is correct to use it with @Injectable, though, provided the string value is given. The following test passes:

@Tested(fullyInitialized = true) Foo sut;
@Injectable String nameForLogger = "foo";

@Test
public void test() {
    assertEquals("foo", sut.logger.getName());
}

Alternatively, the value can be provided by writing @Injectable("foo") String nameForLogger, which can also be done in a test method parameter.

@Vampire
Vampire commented Sep 22, 2016

If you look at the provided MVCE together with my description, you will see that I do not even try to record an expectation on a String. I just use an unmocked String instance in an expectation as parameter for or as return value for some other expectation.

@Vampire
Vampire commented Sep 22, 2016 edited

I guess this has to do with #344. If in the provided test-case I change @Injectable to @Injectable("") (which is the default value anyway), it still fails with the same error. If I change it to @Injectable("f") it suddenly works fine. @Injectable String nameForLogger = "f"; again fails with the error, @Injectable final String nameForLogger = "f"; works fine.

So I'd say somehow JMockit has a special treatment for the empty string which is not good for it.

@rliesenfeld rliesenfeld added bug and removed other labels Sep 22, 2016
@rliesenfeld rliesenfeld self-assigned this Sep 22, 2016
@rliesenfeld
Member

There is indeed a bug here, that I just noted after some experimentation. The real issue is that an "@Injectable String" field seems to be getting partially mocked, when it should not be mocked at all. With a test method parameter, there is no problem. So, it's probably a bug specific to mock fields.

@rliesenfeld rliesenfeld added a commit that closed this issue Sep 24, 2016
@rliesenfeld rliesenfeld Changed the handling and API documentation for an "@Injectable String…
…" without a value, so that the String class is not mocked; closes #340.
64fa071
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment