简体   繁体   中英

Mocking in Intellij doesn't ignore compilation errors in the mocked class?

I'm currently doing a little project as an exercice for a Java Testing course, and we were trying to see how mocking works.

The goal was to see that we could ignore errors in the class that we are mocking.

Here are the three classes used for this exercice:

Collaborateur:

package fr.orsys.tp2junit.prestation;

public class Collaborateur {

        public Collaborateur() {
        }

        public String transformString(String input){
            //Methode avec des bugs
            System.out.println("ok")
            return "ok";
        }
    }

Prestation:

package fr.orsys.tp2junit.prestation;

public class Prestation {

    private Collaborateur collaborateur;

    public Prestation(Collaborateur collaborateur){
        this.collaborateur = collaborateur;
    }

    public String performService(String input){
        return collaborateur.transformString(input);
    }


}

And finally our test class - TestPrestation:

package tp2junit;

import fr.orsys.tp2junit.prestation.Collaborateur;
import fr.orsys.tp2junit.prestation.Prestation;
import org.junit.*;
import static org.junit.Assert.*;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class TestPrestation {

    private Prestation prestation;
    private Collaborateur collaborateur;

    @Before
    public void beforeEachTest(){
        collaborateur = mock(Collaborateur.class);
        prestation = new Prestation(collaborateur);
    }

    @Test
    public void testPerformService(){
        when(collaborateur.transformString("Input")).thenReturn("Ok");
        assertEquals("Ok", prestation.performService("Input"));
    }

}

As you can see in the Collaborateur, there is a missing ';' after the System.out and the goal of the exercice was to show that mocking the class would allow us to ignore that error. Some of my collegues who are working with Eclipse had no issue doing this by using the "Run as JUnit" functionnality.

In Intellij, however I haven't found such an option, I've tried changing the configuration for the 'Before launch' option from 'Build' to 'Build, no error checks' as some StackOverflow posts suggested, but I get the following error when doing so:

java.lang.NoClassDefFoundError: Lfr/orsys/tp2junit/prestation/Collaborateur;

    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
    at java.lang.Class.getDeclaredFields(Class.java:1916)
    at org.junit.runners.model.TestClass.getSortedDeclaredFields(TestClass.java:77)
    at org.junit.runners.model.TestClass.scanAnnotatedMembers(TestClass.java:70)
    at org.junit.runners.model.TestClass.<init>(TestClass.java:57)
    at org.junit.runners.ParentRunner.createTestClass(ParentRunner.java:88)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:83)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
    at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: java.lang.ClassNotFoundException: fr.orsys.tp2junit.prestation.Collaborateur
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    ... 18 more

If anyone has any idea on how to solve this issue that would be really neat, otherwise I guess I'll just have to switch to using Eclipse, which is kind of a bummer cause I really like Intellij.

Mocking should not ignore compile errors, what mocking does is changes behaviour in runtime .

Basic compilation doesn't "half-compile" a class, as in keeps the API but fails the method call, but simply should not generate a .class file, and so you can't even load the class.

The thing is that the eclipse compiler attempts to actually "half-compile" a class, such that the definition is ready but it fails on a call to the un-compiled code (see here ), so that should explain why in eclipse this works, but it is not a feature of the mocking system, rather a feature/bug of the eclipse compiler.

As for switching to eclipse, I would suggest not to switch to eclipse for this, because relying on such a feature seems dangerous, and you should not be trying to run an un-compiled class (see more here ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM