web-dev-qa-db-fra.com

Comment puis-je me moquer de Java.time.LocalDate.now ()

Dans mon cas de test, j'ai besoin d'une méthode de test sensible au temps, dans cette méthode, nous utilisons Java 8 class LocalDate, c'est pas Joda.

Que puis-je faire pour changer l'heure lorsque je lance le test

33
Neil

Dans votre code, remplacez LocalDate.now() par LocalDate.now(clock); .

Vous pouvez ensuite passer Clock.systemDefaultZone() pour la production et ne horloge fixe pour les tests.


Ceci est un exemple :

Commencez par injecter le Clock. Si vous utilisez Spring Boot, faites simplement:

@Bean
public Clock clock() {
    return Clock.systemDefaultZone();
}

Ensuite, appelez LocalDate.now(clock) dans votre code:

@Component
public class SomeClass{

    @Autowired
    private Clock clock;

    public LocalDate someMethod(){
         return LocalDate.now(clock);
    }
}

Maintenant, dans votre classe de test unitaire:

// Some fixed date to make your tests
private final static LocalDate LOCAL_DATE = LocalDate.of(1989, 01, 13);

// mock your tested class
@InjectMocks
private SomeClass someClass;

//Mock your clock bean
@Mock
private Clock clock;

//field that will contain the fixed clock
private Clock fixedClock;


@Before
public void initMocks() {
    MockitoAnnotations.initMocks(this);

    //tell your tests to return the specified LOCAL_DATE when calling LocalDate.now(clock)
    fixedClock = Clock.fixed(LOCAL_DATE.atStartOfDay(ZoneId.systemDefault()).toInstant(), ZoneId.systemDefault());
    doReturn(fixedClock.instant()).when(clock).instant();
    doReturn(fixedClock.getZone()).when(clock).getZone();
}

@Test
public void testSomeMethod(){
    // call the method to test
    LocalDate returnedLocalDate = someClass.someMethod();

    //assert
    assertEquals(LOCAL_DATE, returnedLocalDate);

}

62
assylias

Vous pouvez refactoriser votre code pour le rendre compatible avec les tests, par exemple, remplacer toutes les invocations de LocalDate.now() par l'invocation d'une méthode de classe non statique modifiable personnalisée.

Alternativement, vous pouvez utiliser mockStatic de PowerMock .

4
Aivean

Vous pouvez également vouloir passer une horloge fixe en production (dont la valeur est fixée au début d'une transaction) pour éviter d'utiliser "maintenant" incohérent dans différentes entités et demandes. Voir cette question pour plus de détails.

1
Gebb

Si nous devons nous moquer des méthodes statiques comme now (), nous pouvons utiliser plusieurs alternatives comme PowerMock :

@RunWith(PowerMockRunner.class)
@PrepareForTest({ LocalDateTime.class })
public class LocalDateTimeUnitTest {

    @Test
    public void givenLocalDateTimeMock_whenNow_thenGetFixedLocalDateTime() {
        Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC"));
        LocalDateTime dateTime = LocalDateTime.now(clock);
        mockStatic(LocalDateTime.class);
        when(LocalDateTime.now()).thenReturn(dateTime);
        String dateTimeExpected = "2014-12-22T10:15:30";

        LocalDateTime now = LocalDateTime.now();

        assertThat(now).isEqualTo(dateTimeExpected);
    }
}

Ou JMockit , en effet avec JMockit nous pouvons utiliser la classe MockUp:

@Test
public void givenLocalDateTimeWithJMock_whenNow_thenGetFixedLocalDateTime() {
    Clock clock = Clock.fixed(Instant.parse("2014-12-21T10:15:30.00Z"), ZoneId.of("UTC"));
    new MockUp<LocalDateTime>() {
        @Mock
        public LocalDateTime now() {
            return LocalDateTime.now(clock);
        }
    };
    String dateTimeExpected = "2014-12-21T10:15:30";

    LocalDateTime now = LocalDateTime.now();

    assertThat(now).isEqualTo(dateTimeExpected);
}

Ou la classe Attentes:

@Test
public void givenLocalDateTimeWithExpectations_whenNow_thenGetFixedLocalDateTime() {
    Clock clock = Clock.fixed(Instant.parse("2014-12-23T10:15:30.00Z"), ZoneId.of("UTC"));
    LocalDateTime dateTimeExpected = LocalDateTime.now(clock);
    new Expectations(LocalDateTime.class) {
        {
            LocalDateTime.now();
            result = dateTimeExpected;
        }
    };

    LocalDateTime now = LocalDateTime.now();

    assertThat(now).isEqualTo(dateTimeExpected);
}

Nous pouvons trouver plus d'exemples ici .

Une autre alternative simple consiste à utiliser la méthode now () avec une instance d'horloge fixe. Certes, la plupart des classes du package Java.time ont une méthode now () avec un paramètre Clock :

@Test
public void givenFixedClock_whenNow_thenGetFixedLocalDateTime() {
    Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC"));
    String dateTimeExpected = "2014-12-22T10:15:30";

    LocalDateTime dateTime = LocalDateTime.now(clock);

    assertThat(dateTime).isEqualTo(dateTimeExpected);
}
1
SHoko