Использование PowerMockRunner с классом LocalDate для насмешки сегодняшней даты - PullRequest
0 голосов
/ 02 октября 2018

Рассмотрим класс DateUtilTest следующим образом, который использует PowerMockRunner:

import com.reporting.utils.DateUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.time.LocalDate;
import java.util.Date;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;

@PrepareForTest(DateUtil.class)
@RunWith(PowerMockRunner.class)
public class DateUtilTest {


    @Test
    public void getPreviousWorkingDayAsDate_whenMonday() {
        //given
        LocalDate date = LocalDate.of(2017, 10, 16);
        LocalDate expected = LocalDate.of(2017, 10, 13);

        mockStatic(LocalDate.class);
        when(LocalDate.now()).thenReturn(date);

        //when
        Date previousWorkingDay = DateUtil.getPreviousWorkingDayAsDate();


        //then
        assertEquals(DateUtil.getDateFromLocalDate(expected), previousWorkingDay);
    }

    @Test
    public void getPreviousWorkingDayAsDate2_whenMonday() {
        //given
        LocalDate date = LocalDate.of(2017, 10, 16);


        mockStatic(LocalDate.class);
        when(LocalDate.now()).thenReturn(date);

        //when
        Date previousWorkingDay = DateUtil.getPreviousWorkingDayAsDate();
        LocalDate expected = LocalDate.of(2017, 10, 13);


        //then
        assertEquals(DateUtil.getDateFromLocalDate(expected), previousWorkingDay);
    }

}

Я хочу понять, почему @Test ==> getPreviousWorkingDayAsDate2_whenMonday терпит неудачу при перемещении expected LocalDate инициализация после издевательства над LocalDate.class?

Кроме того, можно ли улучшить эти тесты?

Ответы [ 3 ]

0 голосов
/ 02 октября 2018

Все довольно просто.Когда вы перемещаете ожидаемую инициализацию LocalDate в после пересмешивания LocalDate.class, тогда класс уже смоделирован, глобально, как при каждом обращении к классу.Это означает, что это не дает вам реальную реализацию Java.Это означает, что вы не можете получить реальную реализацию Java LocalDate.of (2017, 10, 13) на java, потому что в этот момент вы переопределили класс с поддельной версией.

Можно ли улучшить тест?Да, не используйте Powermock.

Использование powermock считается плохой практикой, если вы можете его избежать.Это длинная история, и я не уверен, что это место, чтобы объяснить все это.Краткая версия: если вы не используете power mock, вам придется сделать свой код более гибким.Powermock позволяет вам обманывать, а не делать ваш код гибким.Когда вы используете Power Mock, вы не получаете такое же поведение во время теста и производственного кода.

Прочтите здесь для получения дополнительной информации: Почему бы не PowerMock

0 голосов
/ 03 октября 2018

Сроки - это всегда боль при тестировании.Но это можно легко исправить с помощью DateSupplier.

A DateSupplier - это класс, который вы можете добавить везде, где есть дата «сейчас».Замените дату создания на DateSupplier.get().При тестировании вы просто издеваетесь над DateSupplier и возвращаете нужную вам дату.

Сложный пример можно найти здесь: https://dzone.com/articles/mocking-jodatimes-datetime-and. (вам не нужен поставщик Guava)

В этом случае: введите DateSupplier в ваш класс DateUtil и замените его на ложное во время тестирования!

0 голосов
/ 02 октября 2018

Далее, можно ли улучшить эти тесты?

Да - рефакторинг DateUtil, чтобы можно было использовать определенный Clock.Например:

public class DateUtil {
    private static Clock clock = Clock.systemDefaultZone();

    public static setClock(Clock clock) {
        assertNotProduction();  // optionally check for an environment/system variable to throw exception if used in production
        DateUtil.clock = clock;  
    }

   public static Date getPreviousWorkingDayAsDate() {
      LocalDate today = LocalDate.now(clock);   // use clock
      ...
     return ...;
   }
}

Тогда модульный тест не нуждается в насмешках.Например:

@Test
public void getPreviousWorkingDayAsDate_whenMonday() {
    //given
    LocalDate monday = LocalDate.of(2017, 10, 16);
    Clock clock = Clock.fixed(monday.atStartOfDay(ZoneId.systemDefault()).toInstant(), ZoneId.systemDefault());
    DateUtil.setClock(clock);

    LocalDate lastFriday = LocalDate.of(2017, 10, 13);

    //when
    Date previousWorkingDay = DateUtil.getPreviousWorkingDayAsDate();

    //then
    assertEquals(DateUtil.getDateFromLocalDate(lastFriday), previousWorkingDay);
}

@After
public void resetClock() {
    DateUtil.setClock(Clock.systemDefaultZone());
}
...