代码之家  ›  专栏  ›  技术社区  ›  M06H

使用PowerMockRunner和LocalDate类模拟今天的日期

  •  1
  • M06H  · 技术社区  · 6 年前

    考虑一下 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 ==& gt; getPreviousWorkingDayAsDate2_whenMonday 当我移动时失败 expected LocalDate 初始化到模拟后 LocalDate.class ?

    此外,这种测试是否可以改进?

    3 回复  |  直到 6 年前
        1
  •  3
  •   Andrew S    6 年前

    此外,这种测试是否可以改进?

    是-重构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());
    }
    
        2
  •  2
  •   Gonen I    6 年前

    很简单。当您将预期的localdate初始化移动到localdate.class模拟之后,那么该类已经被全局模拟,就像在对该类的每个调用中一样。这意味着它没有给你真正的Java实现。这意味着您无法获得OrthalDeal.Of(2017, 10, 13)的真正Java实现,因为此时您用一个被嘲笑的版本覆盖了该类。

    测试可以改进吗?是的,不要使用powermock。

    如果可以避免,使用powermock被认为是不好的做法。说来话长,我不确定这是解释一切的地方。它的简短版本:如果不使用PowerMock,则必须使代码更加灵活。PowerMock允许您作弊,而不是使代码灵活。当您使用PowerMock时,在您的测试和生产代码中不会得到相同的行为。

    阅读此处了解更多信息: Why not PowerMock

        3
  •  1
  •   Tom Van Rossom    6 年前

    测试时约会总是很痛苦的。但使用 DateSupplier .

    数据追加器 是一个类,您可以在任何创建了“现在”日期的地方注入。 将创建日期替换为 DateSupplier.get() . 测试时,您只需模拟日期供应商并返回您想要的日期。

    这里有一个详细的例子: https://dzone.com/articles/mocking-jodatimes-datetime-and . (你不需要番石榴的供应商)

    在这种情况下:注入 数据追加器 在你 DateUtil 类,并在测试期间将其替换为模拟!