如何使用 Mockito 在 Java 中模拟 new Date()

新手上路,请多包涵

我有一个使用当前时间进行一些计算的函数。我想用 mockito 来模拟它。

我想测试的类的一个例子:

 public class ClassToTest {
    public long getDoubleTime(){
        return new Date().getTime()*2;
    }
}

我想要这样的东西:

 @Test
public void testDoubleTime(){
   mockDateSomeHow(Date.class).when(getTime()).return(30);
   assertEquals(60,new ClassToTest().getDoubleTime());
}

有可能嘲笑吗?我不想更改“已测试”代码以便进行测试。

原文由 Jordi P.S. 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.9k
2 个回答

正确的做法是重构您的代码,使其更易于测试,如下所示。重构您的代码以删除对 Date 的直接依赖将允许您为正常运行时和测试运行时注入不同的实现:

 interface DateTime {
    Date getDate();
}

class DateTimeImpl implements DateTime {
    @Override
    public Date getDate() {
       return new Date();
    }
}

class MyClass {

    private final DateTime dateTime;
    // inject your Mock DateTime when testing other wise inject DateTimeImpl

    public MyClass(final DateTime dateTime) {
        this.dateTime = dateTime;
    }

    public long getDoubleTime(){
        return dateTime.getDate().getTime()*2;
    }
}

public class MyClassTest {
    private MyClass myClassTest;

    @Before
    public void setUp() {
        final Date date = Mockito.mock(Date.class);
        Mockito.when(date.getTime()).thenReturn(30L);

        final DateTime dt = Mockito.mock(DateTime.class);
        Mockito.when(dt.getDate()).thenReturn(date);

        myClassTest = new MyClass(dt);
    }

    @Test
    public void someTest() {
        final long doubleTime = myClassTest.getDoubleTime();
        assertEquals(60, doubleTime);
    }
}

原文由 munyengm 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果您有无法重构的遗留代码,并且不想影响 System.currentTimeMillis() ,请尝试使用 PowermockPowerMockito

 //note the static import
import static org.powermock.api.mockito.PowerMockito.whenNew;

@PrepareForTest({ LegacyClassA.class, LegacyClassB.class })

@Before
public void setUp() throws Exception {

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("PST"));

    Date NOW = sdf.parse("2015-05-23 00:00:00");

    // everytime we call new Date() inside a method of any class
    // declared in @PrepareForTest we will get the NOW instance
    whenNew(Date.class).withNoArguments().thenReturn(NOW);

}

public class LegacyClassA {
  public Date getSomeDate() {
     return new Date(); //returns NOW
  }
}

原文由 Daniel Mora 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题