web-dev-qa-db-fra.com

Méthode finale moqueuse

J'ai besoin de simuler un cours avec la méthode finale en utilisant mockito. J'ai écrit quelque chose comme ça 

@Test
public void test() {
    B b = mock(B.class);
    doReturn("bar called").when(b).bar();   
    assertEquals("must be \"overrided\"", "bar called", b.bar());
    //bla-bla
}


class B {
    public final String bar() {
        return "fail";
    }
}

Mais ça échoue. J'ai essayé du "bidouillage" et ça marche.

   @Test
   public void hackTest() {
        class NewB extends B {
            public String barForTest() {
                return bar();
            }
        }
        NewB b = mock(NewB.class);
        doReturn("bar called").when(b).barForTest();
        assertEquals("must be \"overrided\"", "bar called", b.barForTest());
    }

Cela fonctionne, mais "sent".

Alors, où est le bon chemin?

Merci.

51
Stan Kurilin

Il n'y a pas de support pour se moquer des méthodes finales dans Mockito.

Comme Jon Skeet l'a commenté, vous devriez rechercher un moyen d'éviter la dépendance à la méthode finale. Cela dit, il existe des moyens de contourner la manipulation de bytecode (par exemple avec PowerMock)

Un comparaison entre Mockito et PowerMock expliquera les choses en détail.

28
iwein

Depuis le Mockito FAQ :

Quelles sont les limites de Mockito

  • Impossible de se moquer des méthodes finales - leur comportement réel est exécuté sans aucune exception. Mockito ne peut pas vous avertir de vous moquer des méthodes finales, soyez donc vigilant.
30
matt b

Vous pouvez utiliser Powermock avec Mockito, vous n’avez donc pas besoin de sous-classe B.class. Ajoutez simplement ceci au sommet de votre classe de test

@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)

@PrepareForTest demande à Powermock d’instrumenter B.class pour que les méthodes finale et statique soient moqueuses. Un inconvénient de cette approche est que vous devez utiliser PowerMockRunner, ce qui empêche l'utilisation d'autres programmes de test, tels que le programme de test Spring.

17
Justin Rowe

Mockito 2 prend désormais en charge les méthodes finales moqueuses, mais il s’agit d’une fonctionnalité «d’incubation». Pour l'activer, procédez comme suit: https://github.com/mockito/mockito/wiki/What's-new-in-Mockito-2#mock-the-unmockable-opt-in méthodes de moquage des classes finales

13
WindRider

En supposant que la classe B soit comme ci-dessous:

class B {
    private String barValue;
    public final String bar() {
        return barValue;
    }
    public void final setBar(String barValue) {
        this.barValue = barValue;
    }
}

Il existe un meilleur moyen de le faire sans utiliser le framework PowerMockito . Vous pouvez créer un espion pour votre classe et vous moquer de votre méthode finale.

@Test
public void test() {

    B b  = new B();
    b.setBar("bar called") //This should the expected output:final_method_bar()
    B spyB = Mockito.spy(b);
    assertEquals("bar called", spyB.bar());

}
3
Murtuza Mithaiwala

Mockito 2.x prend désormais en charge la méthode finale et le stubbing de classe final.

À partir de la documentation :

Le moquage des classes et méthodes finales est une fonction d’incubation à acceptation. Cette fonctionnalité doit être explicitement activée en créant le fichier src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker contenant une seule ligne:

mock-maker-inline

Après avoir créé ce fichier, vous pouvez faire:

final class FinalClass {
  final String finalMethod() { return "something"; }
}

FinalClass concrete = new FinalClass(); 

FinalClass mock = mock(FinalClass.class);
given(mock.finalMethod()).willReturn("not anymore");

assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());

Lors des étapes suivantes, l’équipe apportera un moyen programmatique d’utiliser cette fonctionnalité. Nous identifierons et fournirons une assistance pour tous les scénarios inacceptables.

2
Cypress Frankenfeld

Je viens de faire la même chose. Mon cas était que je voulais m'assurer que la méthode ne "causait" pas d'erreur mais comme c'est une méthode catch/log/return, je ne pouvais pas le tester directement sans modifier la classe.

Je voulais simplement me moquer de l'enregistreur que je transmettais, mais quelque chose à propos de se moquer de l'interface "Journal" ne semblait pas fonctionner et se moquer d'une classe comme "SimpleLog" ne fonctionnait pas car ces méthodes sont finales.

J'ai fini par créer une classe interne anonyme étendant SimpleLog qui redéfinissait la méthode "log (niveau, chaîne, erreur)" au niveau de base à laquelle tous les autres déléguaient, puis attendait simplement un appel avec un "niveau" de 5.

En général, prolonger un cours sur le comportement n'est pas vraiment une mauvaise idée, mais il serait peut-être préférable de se moquer de toute façon si ce n'est pas trop compliqué.

0
Bill K