web-dev-qa-db-fra.com

pourquoi ne pouvons-nous pas créer un espion pour le constructeur paramétré en utilisant Mockito

J'ai seulement un constructeur paramétré dans mon code et j'ai besoin de l'injecter à travers.

Je veux espionner le constructeur paramétré pour injecter un objet factice comme dépendance pour mon junit.

public RegDao(){
 //original object instantiation here
Notification ....
EntryService .....
}

public RegDao(Notification notification , EntryService entry) {
 // initialize here
}

we have something like below : 
RegDao dao = Mockito.spy(RegDao.class);

Mais avons-nous quelque chose que je peux injecter un objet simulé dans le constructeur et l'espionner?.

14
Pradeep

Vous pouvez le faire en instanciant votre classe principale avec un constructeur paramétré dans votre junit, puis en créant un espion.

Supposons que votre classe principale soit A. Où B et C sont ses dépendances

public class A {

    private B b;

    private C c;

    public A(B b,C c)
    {
        this.b=b;
        this.c=c;
    }

    void method() {
        System.out.println("A's method called");
        b.method();
        c.method();
        System.out.println(method2());

    }

    protected int method2() {
        return 10;
    }
}

Ensuite, vous pouvez écrire junit pour cela en utilisant votre classe paramétrée comme ci-dessous

@RunWith(MockitoJUnitRunner.class)
public class ATest {

    A a;

    @Mock
    B b;

    @Mock
    C c;

    @Test
    public void test() {
        a=new A(b, c);
        A spyA=Mockito.spy(a);

        doReturn(20).when(spyA).method2();

        spyA.method();
    }
}

Sortie de la classe de test

A's method called
20
  1. Ici B et C sont des objets simulés que vous avez injectés dans votre classe A à l'aide du constructeur paramétré.
  2. Ensuite, nous avons créé un spy de A appelé spyA.
  3. Nous avons vérifié si spy fonctionne vraiment en modifiant la valeur de retour d'une méthode protégée method2 dans la classe A qui n'aurait pas pu être possible si spyA n'était pas un spy réel de A.
20
Dhawal Kapil

Il semble que vous manquez peut-être une solution d'injection de dépendance. Mockito est idéal pour travailler avec votre DI pour injecter des mocks. Par exemple, vous pouvez utiliser CDI, annoter vos membres Notification et EntryService avec @Inject, déclarer @Mocks pour les deux dans votre test, puis laissez Mockito les injecter dans votre RegDao pour les tester.

Voici une maquette de travail du test, je pense que vous essayez d'exécuter:

import static org.junit.Assert.assertEquals;

import javax.inject.Inject;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MockitoSpyInjection {
    static class Notification { }
    static class EntryService { }
    static class RegDao {
        @Inject
        Notification foo;

        @Inject
        EntryService  bar;

        public RegDao() {
        }

        public RegDao(Notification foo, EntryService bar) {
            this.foo = foo;
            this.bar = bar;
        }

        public Notification getFoo() {
            return foo;
        }

        public EntryService getBar() {
            return bar;
        }

    }


    @Mock
    Notification foo;

    @Mock
    EntryService bar;

    @Spy
    @InjectMocks
    RegDao dao;

    @Test
    public void test() {
        assertEquals(foo, dao.getFoo());
        assertEquals(bar, dao.getBar());
    }
}
0
Isaac Truett