2010-11-14 35 views
7

J'ai rencontré un problème avec mockito. Je développe une application web. Dans mes tests, la gestion des utilisateurs est raillée. Il y a des cas où je dois modifier l'utilisateur renvoyé par la méthode getLoggedInUser(). Le problème est que ma méthode getLoggedInUser() peut également lancer un AuthenticationException.Mockito re-stub méthode déjà écrasée avec thenthrow

Alors, quand je tente de passer d'aucun utilisateur à certains utilisateurs, l'appel à

when(userProvider.getLoggedInUser()).thenReturn(user); 

jette une exception, comme userProvider.getLoggedInUser() est déjà écrasa avec thenTrow()

Est-il possible de dire la when méthode de ne pas se soucier des exceptions?

Merci à l'avance - István

+0

Merci les gars pour les réponses! En résumé: c'est probablement à cause de la mauvaise conception du logiciel que j'ai besoin de recréer la méthode. Mais pour l'instant c'est facile pour moi, et les tests semblent aussi propres. J'ai fait d'autres recherches et j'ai trouvé la méthode Mockito.reset (T ... mocks), qui fait l'affaire pour moi. La prochaine fois je vais trouver un design plus simple :) – Szobi

Répondre

2

Ma première réaction à votre question est qu'il semble que vous essayez d'en faire trop en un seul test.

Pour faciliter les tests et la simplicité, chaque test ne doit tester qu'une seule chose. C'est la même chose que le Single Responsibility Principle. Je trouve souvent des programmeurs essayant de tester plusieurs choses dans un test et ayant toutes sortes de problèmes à cause de cela. Ainsi, chacune de vos méthodes de test unitaires doit suivre ce flux:

  1. Configurer un scénario unique pour le test.
  2. Appelez la classe testée pour déclencher le code testé.
  3. Vérifiez le comportement.

Donc dans votre cas, je m'attendrais à voir au moins deux tests. Un où getLoggedInUser() renvoie un utilisateur, et un où getLoggedInUser() lève une exception. De cette façon, vous n'aurez pas de problème à essayer de simuler un comportement différent dans le simulacre.

La deuxième pensée qui vient à l'esprit n'est pas de boutonner. Cherchez à utiliser plutôt parce que vous pouvez configurer une série d'attentes. C'est à dire. le premier appel renvoie un utilisateur, le deuxième appel émet une exception, le troisième appelle un utilisateur différent, etc.

+1

Un exemple d'utilisation de 'expect' ou un lien vers la documentation/tutoriels serait apprécié :) –

2

Il semble que vous pourriez avoir à utiliser une réponse personnalisée. Here is an example.

+0

Merci javamonkey, c'est aussi une solution raisonnable, mais pour l'instant je vais rester avec Mockito.reset(). – Szobi

+0

Intéressant - Je vais vous donner le +1 sur la question en général pour l'information que je viens d'apprendre sur la réinitialisation. Je suis sûr que vous l'avez lu aussi, donc je ne vais pas le répéter ... bonnes choses :) – javamonkey79

+0

Merci pour le +1 :) – Szobi

1

Est-il possible de dire la méthode quand ne pas se soucier des exceptions?

Pour répondre à cette question en fait:

import static org.hamcrest.Matchers.equalTo; 
import static org.hamcrest.Matchers.is; 
import static org.junit.Assert.assertThat; 
import static org.mockito.ArgumentMatchers.any; 
import static org.powermock.api.mockito.PowerMockito.mock; 
import static org.powermock.api.mockito.PowerMockito.when; 

import org.junit.Test; 
import org.mockito.Mockito; 

import java.util.ArrayList; 

public class MyTest { 

    @Test 
    public void testA() { 

     // setup 
     ArrayList<Object> list = mock(ObjectArrayList.class); 
     when(list.indexOf(any())).thenReturn(6); 
     when(list.indexOf(any())).thenReturn(12); 

     // execute 
     int index = list.indexOf(new Object()); 

     // verify 
     assertThat(index, is(equalTo(12))); 
    } 

    @Test 
    public void testB() { 

     // setup 
     ArrayList<Object> list = mock(ObjectArrayList.class); 
     when(list.add(any())).thenThrow(new AssertionError("can't get rid of me!")); 
     when(list.add(any())).thenReturn(true); 

     // execute 
     list.add(new Object()); 
    } 

    @Test 
    public void testC() { 

     // setup 
     ArrayList<Object> list = mock(ObjectArrayList.class); 
     when(list.add(any())).thenThrow(new AssertionError("can't get rid of me!")); 
     Mockito.reset(list); 
     when(list.add(any())).thenReturn(true); 

     // execute 
     list.add(new Object()); 
    } 

    /** 
    * Exists to work around the fact that mocking an ArrayList<Object> 
    * requires a cast, which causes "unchecked" warnings, that can only be suppressed... 
    */ 
    class ObjectArrayList extends ArrayList<Object> { 

    } 
} 

TestB échoue en raison de l'assertion que vous ne pouvez pas vous débarrasser.TestC montre comment la méthode reset peut être utilisée pour réinitialiser le témoin et supprimer la commande thenThrow.

Notez que la réinitialisation ne semble pas toujours fonctionner dans certains exemples plus complexes que j'ai. Je suppose que c'est peut-être parce qu'ils utilisent PowerMockito.mock plutôt que Mockito.mock?