web-dev-qa-db-fra.com

Mockito simule une implémentation de méthode réelle lors d'une tentative de stub de protection du paquet

J'essaie de remplacer une méthode à l'aide de Mockito 1.8.5, mais cela appelle la mise en œuvre réelle de la méthode (avec "" comme valeurs parm) qui lève une exception.

package background.internal; //located in trunk/tests/Java/background/internal

public class MoveStepTest {

    @Test
    public void testMoveUpdate() {
        final String returnValue = "value";
        final FileAttachmentContainer file = mock(FileAttachmentContainer.class);
        doReturn(returnValue).when(file).moveAttachment(anyString(), anyString(), anyString());
        //this also fails
        //when(file.moveAttachment(anyString(), anyString(), anyString())).thenReturn(returnValue);

        final AttachmentMoveStep move = new AttachmentMoveStep(file);
        final Action moveResult = move.advance(1, mock(Context.class));
        assertEquals(Action.done, moveResult);
    }
}

La méthode que je suis en train de simuler ressemble à ceci. Il n'y a pas de méthode finale ni de cours. 

package background.internal; //located in trunk/src/background/internal


   public class FileAttachmentContainer {
        String moveAttachment(final String arg1, final String arg2, final String arg3) 
                throws CustomException {
            ...
        }

        String getPersistedValue(final Context context) {
           ...     
        }
    }

Et la classe que je passe la maquette ressemble à ceci:

package background.internal; //located in trunk/src/background/internal
public class AttachmentMoveStep {

    private final FileAttachmentContainer file;

    public AttachmentMoveStep(final FileAttachmentContainer file) {
        this.file = file;        
    }

    public Action advance(final double acceleration, final Context context) {
        try {
            final String attachmentValue = this.file.getPersistedValue(context);
            final String entryId = this.file.moveAttachment(attachmentValue, "attachment", context.getUserName());

            //do some other stuff with entryId
        } catch (CustomException e) {
            e.log(context);
        }    
        return Action.done;
    }
}

Qu'est-ce qui provoque l'invocation de l'implémentation réelle et comment puis-je l'empêcher?

22
Jake Walsh

La méthode que vous vous moquez n'est pas accessible au code Mockito. 

Parce que votre code de test et votre code à tester sont dans le même package, le compilateur vous permet de configurer votre maquette de cette façon, mais au moment de l'exécution, la bibliothèque Mockito doit essayer d'accéder à moveAttachment, mais cela ne fonctionne pas dans votre cas. Cela semble être un bug ou limitation connue dans Mockito comme il devrait supporter ce cas (et le supporte dans la plupart des cas).

La chose la plus simple à faire serait de rendre moveAttachment une méthode publique. Si ce n’est pas une option, demandez-vous d’abord si vous voulez vous moquer de lui. Que se passe-t-il si la méthode réelle est appelée? 

La dernière option consiste à utiliser PowerMock pour traiter la méthode moveAttachment en tant que méthode privée et la simuler de cette façon.

19
jhericks

Je ne suis pas d'accord avec la réponse acceptée.

Je pense que vous devez fournir plus de détails sur votre environnement. Je ne peux pas reproduire votre problème. J'écris le code suivant dans un projet maven:

package background.internal; //located in src/main/Java

public class FileAttachmentContainer {
    String moveAttachment(String arg1, String arg2, String arg3) {
        throw new IllegalStateException();
    }

    String getPersistedValue(Context context) {
        throw new IllegalStateException();
    }
}

et

package background.internal;

public class AttachmentMoveStep {

    private FileAttachmentContainer file;

    public AttachmentMoveStep(FileAttachmentContainer file) {
        this.file = file;
    }

    public Action advance(double acceleration, Context context) {
        String attachmentValue = file.getPersistedValue(context);
        file.moveAttachment(attachmentValue, "attachment", context.getUserName());
        return Action.done;
    }
}

et le test suivant

package background.internal; //located in src/test/Java

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

import org.junit.Test;

public class MoveStepTest {

    @Test
    public void testMoveUpdate() {
        String returnValue = "value";
        FileAttachmentContainer file = mock(FileAttachmentContainer.class);
        doReturn(returnValue).when(file).moveAttachment(anyString(), anyString(), anyString());
        //this also works
        //when(file.moveAttachment(anyString(), anyString(), anyString())).thenReturn(returnValue);

        AttachmentMoveStep move = new AttachmentMoveStep(file);
        Action moveResult = move.advance(1, mock(Context.class));
        assertEquals(Action.done, moveResult);
    }
}

Mon projet utilise les dépendances suivantes:

  • jdk1.7.0_05
  • junit-4.10.jar
  • mockito-all-1.9.0.jar
  • javassist-3.16.1-GA.jar
  • objenesis-1.2.jar
  • hamcrest-core-1.1.jar
0
gontard