web-dev-qa-db-fra.com

java: comment se moquer de Calendar.getInstance ()?

Dans mon code, j'ai quelque chose comme ça:

private void doSomething() {
   Calendar today = Calendar.getInstance();
   ....
}

Comment puis-je "me moquer" de mon test Junit pour renvoyer une date spécifique?

22
Randomize

Pour autant que je sache, vous avez trois options judicieuses:

  1. Injectez l’instance Calendar dans n’importe quelle méthode/classe dans laquelle vous avez défini ce jour.

    private void method(final Calendar cal) { Date today = cal.getTime(); }

  2. Utilisez JodaTime au lieu de Calendar. C'est moins une option qu'une suggestion, car JodaTime vous facilitera grandement la vie. Vous aurez toujours besoin d'injecter cette fois-ci dans la méthode.

    DateTime dt = new DateTime();

    Date jdkDate = dt.toDate();

  3. Enroulez Calendar dans une interface qui vous permet de récupérer l'heure. Vous vous contentez alors de vous moquer de cette interface et de la faire renvoyer une constante Date.

    Date today = calendarInterfaceInstance.getCurrentDate()

16
BeRecursive

Vous pouvez vous en moquer en utilisant PowerMock en combinaison avec Mockito:

En plus de votre classe:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassThatCallsTheCalendar.class})

La clé du succès est que vous devez placer la classe dans laquelle vous utilisez Calendar dans PrepareForTest au lieu de Calendar elle-même, car il s'agit d'une classe système. (J'ai personnellement dû chercher beaucoup avant de trouver ceci) 

Puis le se moquer de lui-même:

mockStatic(Calendar.class);
when(Calendar.getInstance()).thenReturn(calendar);
13
GoGoris

Ne vous moquez pas de vous - introduisez plutôt une méthode que vous pouvez simuler et qui permet d’obtenir des dates. Quelque chose comme ça:

interface Utility {

    Date getDate();
}

Utilities implements Utility {


    public Date getDate() {

        return Calendar.getInstance().getTime();
    }

}

Ensuite, vous pouvez l'injecter dans votre classe ou simplement utiliser une classe auxiliaire avec un tas de méthodes statiques avec une méthode de chargement pour l'interface:

public class AppUtil {

    private static Utility util = new Utilities();

    public static void load(Utility newUtil) {

         this.util = newUtil;
    }

    public static Date getDate() {

        return util.getDate();
    }

}

Puis dans votre code d'application: 

private void doSomething() {
   Date today = AppUtil.getDate();
   ....
}

Vous pouvez alors simplement charger une interface fictive dans vos méthodes de test.

@Test
public void shouldDoSomethingUseful() {
     Utility mockUtility = // .. create mock here
     AppUtil.load(mockUtility);

     // .. set up your expectations

     // exercise the functionality
     classUnderTest.doSomethingViaAPI();

     // ... maybe assert something 

}

Voir aussi Ne devriez-vous que simuler des types que vous possédez? et Test odeur - tout est ridiculisé

9
blank

Utilisation de Mockito et PowerMockito:

Calendar endOfMarch = Calendar.getInstance();
endOfMarch.set(2011, Calendar.MARCH, 27);
PowerMockito.mockStatic(Calendar.class);
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch);

Référez-vous au link pour le code complet.

6
Surekha

Ecrivez une classe appelée DateHelper avec une méthode getCalendar qui retourne Calendar.getInstance(). Refactorisez la classe que vous testez afin qu’elle ait une variable membre de type DateHelper et un constructeur qui injecte cette variable membre. Utilisez ce constructeur dans votre test pour injecter un modèle de DateHelper, dans lequel getCalendar a été modifié pour renvoyer une date connue.

2
Dawood ibn Kareem

Vous pouvez mockit en utilisant JMockit. Ici, vous pouvez voir comment vous pouvez le faire: Calendrier Java simulé - JMockit vs Mockito .

1
Behrang

Pour ceux qui suivent le modèle MVP se moquant de Calendrier, c'est un jeu d'enfant:

  1. Dans un présentateur, créez une méthode qui renvoie une instance de calendrier:

     public Calendar getCurrentTime() {  
            return Calendar.getInstance();    
        }
    
  2. Dans votre vue (Activité, Fragment, etc.), vous accédez au calendrier à l'aide du présentateur:

     Calendar calendar = mPresenter.getCurrentTime();   
     // do whatever you want
    
  3. Dans vos tests, vous faites:

     // create a dummy calendar   
     Calendar mockCalendar = ...   
     // You've already mocked your Presenter, haven't you?   
     when(mMockPresenter.getCurrentTime()).thenReturn(mockCalendar);   
     // here you are!
    
0
Leo Droidcoder