6 votes

Comment vérifier si une méthode est appelée sur le système testé (pas un mock) ?

J'essaie d'écrire un test unitaire qui doit confirmer si une méthode est appelée ou non. J'utilise JUnit, Mockito et PowerMock.

public class Invoice
{

  protected void createInvoice()
  {
    // random stuff here
    markInvoiceAsBilled("57");
  }

  protected void markInvoiceAsBilled(String code)
  {
    // marked as billed
  } 
}

Donc, voici mon système en cours de test Invoice . J'exécute ce test :

  public class InvoiceTest
  {
    @Test
    public void testInvoiceMarkedAsBilled()
    {
      Invoice sut = new Invoice();
      Invoice sutSpy = spy(sut);

      sut.createInvoice();

      // I want to verify that markInvoiceAsBilled() was called
    }
  }

Cet exemple est juste un exemple de ce à quoi le code réel ressemble....

Mon problème est que mockito dit que vous pouvez seulement vérifier si une méthode est appelée sur un objet mocké... mais je ne veux pas mocker cet objet, car c'est mon objet sous test. Je sais que vous pouvez espionner l'objet que vous testez, alors voici ce que j'ai essayé :

  verify(sutSpy).markInvoiceAsBilled("57");

Ce que j'essaie de faire n'est-il pas possible ? Ou est-ce que je m'y prends mal ?

Merci à tous :)

10voto

matt b Points 73770

Je ne suis pas sûr que ce que vous essayez de faire soit la meilleure façon de procéder.

Je ne me préoccuperais pas de vérifier que Invoice.createInvoice() appelle une méthode interne et privée markInvoiceAsBilled() - au lieu de tester que l'appel createInvoice() modifie l'état de l'objet Facture de la façon dont vous vous y attendez - c'est-à-dire, que status est maintenant BILLED ou quelque chose de similaire.

En d'autres termes - ne testez pas les méthodes appelées par createInvoice() - vérifiez qu'après avoir appelé cette méthode, le état de l'objet est ce que vous attendez.

1voto

Je suis d'accord avec la réponse de matt-b. Ceci étant dit, en fonction du cas d'utilisation et de la complexité de la méthode, vous pouvez revoir la conception de votre unité afin qu'elle puisse être testée.

Disons par exemple que votre objet devient beaucoup plus compliqué, par ex.

public A {
  public a() {
    b();
    c();
  }

  public b() { /** hairy code, many branches to test */ }
  public c() { /** hairy code, many branches to test */ }
}

La couverture de b par des tests et de c par des tests est simple, mais la couverture de a semble être un problème puisque vous dépendez des méthodes b et c.

Considérez plutôt cette conception

public A {
  private final Dep mDep;

  public a() {
    mDep.b();
    mDep.c();
  }

  public b() { 
    mDep.b(); 
  }

  public c() { 
    mDep.c();
  }

  // dependency abstraction we create to help test
  static class Dep {
    public b() { /** hairy code, many branches to test */ }
    public c() { /** hairy code, many branches to test */ }
  }
}

Maintenant, le test A.a , A.b y A.c vous demande juste de vérifier votre mDep est appelé (parmi toutes les autres actions de la méthode). Séparément, vous testez A.Dep.b y A.Dep.c méthodes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X