Using JMockit in WildFly will give many false-positive "internal class mocked" warnings #339

Closed
Vampire opened this Issue Sep 21, 2016 · 5 comments

Projects

None yet

2 participants

@Vampire
Vampire commented Sep 21, 2016

If you use JMockit within WildFly, the calculation whether a MockUp target class is internal or not is not working properly.

Each MockUp you create that mocks a class that is one of your libs (not a JRE class or something that is shipped with the app-server, but shipped with your EAR) will produce the "internal class mocked" warning, even the three JMockit-internal startup mocks are affected.

e. g. the JMockit-internal startup mocks for org.junit.runner.notification.RunNotifier, org.junit.runners.BlockJUnit4ClassRunner and org.junit.runners.model.FrameworkMethod will produce the warning, because in mockit.MockUp.areClassesFromSameCodebase():260 the variable values are

src1: java.security.CodeSource  = {java.security.CodeSource@28551} "(vfs:/D:/Programme/wildfly-8.1.0.Final/content/mod-cm-integTest-2016R2.ear/lib/jmockit-1.27.jar <no signer certificates>)"
src2: java.security.CodeSource  = {java.security.CodeSource@28552} "(vfs:/D:/Programme/wildfly-8.1.0.Final/content/mod-cm-integTest-2016R2.ear/lib/arquillian-junit.jar <no signer certificates>)"
location1: java.net.URL  = {java.net.URL@28603} "vfs:/D:/Programme/wildfly-8.1.0.Final/content/mod-cm-integTest-2016R2.ear/lib/jmockit-1.27.jar"
location2: java.net.URL  = {java.net.URL@28604} "vfs:/D:/Programme/wildfly-8.1.0.Final/content/mod-cm-integTest-2016R2.ear/lib/arquillian-junit.jar"
codebase1: java.lang.String  = "D:\Programme\wildfly-8.1.0.Final\content\mod-cm-integTest-2016R2.ear\lib"
codebase2: java.lang.String  = "D:\Programme\wildfly-8.1.0.Final\content\mod-cm-integTest-2016R2.ear\lib"

having a mock like the following

new MockUp<org.apache.commons.codec.binary.Base64>() {
    @Mock
    boolean isBase64(Invocation invocation, String base64) {
        return false;
    }
};

which is definitely not in our codebase also gives the warning, this time the fields are

src1: java.security.CodeSource  = {java.security.CodeSource@22833} "(vfs:/D:/Programme/wildfly-8.1.0.Final_EAP/content/mod-cm-integTest-2016R2.ear/lib/mod-cm-integTest-2016R2.jar <no signer certificates>)"
src2: java.security.CodeSource  = {java.security.CodeSource@22834} "(vfs:/D:/Programme/wildfly-8.1.0.Final_EAP/content/mod-cm-integTest-2016R2.ear/lib/commons-codec-1.6.jar <no signer certificates>)"
location1: java.net.URL  = {java.net.URL@22835} "vfs:/D:/Programme/wildfly-8.1.0.Final_EAP/content/mod-cm-integTest-2016R2.ear/lib/mod-cm-integTest-2016R2.jar"
location2: java.net.URL  = {java.net.URL@22836} "vfs:/D:/Programme/wildfly-8.1.0.Final_EAP/content/mod-cm-integTest-2016R2.ear/lib/commons-codec-1.6.jar"
codebase1: java.lang.String  = "D:\Programme\wildfly-8.1.0.Final_EAP\content\mod-cm-integTest-2016R2.ear\lib"
codebase2: java.lang.String  = "D:\Programme\wildfly-8.1.0.Final_EAP\content\mod-cm-integTest-2016R2.ear\lib"

As the own code can be defined in an arbitrary amount of own JARs, it is hard to say which classes are internal and which are external.

@rliesenfeld rliesenfeld added the bug label Sep 21, 2016
@rliesenfeld rliesenfeld self-assigned this Sep 21, 2016
@rliesenfeld
Member

Thanks. The current implementation fails to properly check for mockup and target classes that come from jar files. This should be easy to fix.

@Vampire
Vampire commented Sep 22, 2016

You think so? Besides that the locations don't necessarily need to include the JAR name per-se, you then still cannot reliably do the validation you wanted. You can change it so that the false-positives are away, but you will probably also remove most of the real findings if you restrict the check on JAR, because target and mockup will not be in the same JAR.

@Vampire
Vampire commented Sep 22, 2016

Your test is also highly test-runner specific anyway. One example, I use Gradle to run normal JUnit tests with JMockit. I have multiple projects and multiple sourcesets. In the example I tested now I have a test in the test sourceset of module central-suite that creates a MockUp for a class in the shared sourceset of module central-suite. This will not trigger the warning, because of the following values:

src1: java.security.CodeSource  = {java.security.CodeSource@2449} "(file:/D:/Sourcecode/EMPIC/EAP/EmpicSuite/central-suite/build/classes/test/ <no signer certificates>)"
src2: java.security.CodeSource  = {java.security.CodeSource@2450} "(file:/D:/Sourcecode/EMPIC/EAP/EmpicSuite/central-suite/build/libs/central-suite-shared-2016R2.jar <no signer certificates>)"
location1: java.net.URL  = {java.net.URL@2451} "file:/D:/Sourcecode/EMPIC/EAP/EmpicSuite/central-suite/build/classes/test/"
location2: java.net.URL  = {java.net.URL@2452} "file:/D:/Sourcecode/EMPIC/EAP/EmpicSuite/central-suite/build/libs/central-suite-shared-2016R2.jar"
codebase1: java.lang.String  = "D:\Sourcecode\EMPIC\EAP\EmpicSuite\central-suite\build\classes"
codebase2: java.lang.String  = "D:\Sourcecode\EMPIC\EAP\EmpicSuite\central-suite\build\libs"

So the check you do is very much dependent on the used toolchain.

@Vampire
Vampire commented Sep 22, 2016

Here you have a minimal example Gradle project where you see this: test.zip
If you unzip this and execute gradlew test -i, you will see that you get a warning for mocking main.Foo, but no warning for foo.Foo.

@Vampire
Vampire commented Sep 25, 2016

May I ask whether this will get some fix for the version released soon?

@rliesenfeld rliesenfeld added a commit that closed this issue Sep 25, 2016
@rliesenfeld rliesenfeld Improved the check that compares the "codebases" of a mockup class an…
…d its target class, to properly handle jar files; closes #339.
42751db
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment