如何使用JMockit模拟Date类的默认构造函数?

asm*_*ier 3 java jmockit default-constructor

我想模拟默认构造函数,java.util.date因此它不会构造一个Date表示创建时间的对象,但始终是相同的Date对象(在我2010年12月31日的示例中).我尝试用JMockit和执行此操作JUnit,但在执行下面的测试时,输出始终是Thu Jan 01 01:00:00 CET 1970.那我的模拟有Date()什么问题?

import java.util.Date;

import org.junit.*;
import mockit.*;

public class AppTest {

    @Before
    public void setUp() {
        Mockit.setUpMocks(MockedDate.class);
    }

    @After
    public void tearDown() {
        Mockit.tearDownMocks();
    }  

   @Test
    public void testDate() {
        Date today=new Date();
        System.out.println(today.toString());
    }

    @MockClass(realClass=Date.class)
    public static class MockedDate {

        @Mock
        public void $init() {
            // Now should be always 31.12.2010!
            new Date(110,11,31);  //110 = 2010! 11 = December! This is sick!
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

asm*_*ier 10

al nik的答案对我来说是一个很好的暗示.最好是模拟System类而不是Date类来生成假时间.我自己的解决方案最终只是模拟System.currentTimeMillis()方法(此方法由Date()内部调用).

JMockit 1.5及更高版本

new MockUp<System>(){

    @Mock
    public long currentTimeMillis() {

        // Now is always 11/11/2011
        Date fake = new Date(111,10,11);
        return fake.getTime();
    }
};
Run Code Online (Sandbox Code Playgroud)

JMockit 1.4及更早版本

@MockClass(realClass = System.class)
public static class MockedSystem {

    @Mock
    public long currentTimeMillis() {

        // Now is always 11/11/2011
        Date fake = new Date(111,10,11);
        return fake.getTime();
    }
}
Run Code Online (Sandbox Code Playgroud)


mic*_*son 9

正如测试驱动书中所建议的那样,在java类中使用SystemTime抽象是一种很好的做法.替换方法调用(System#currentTimeMillis和Calendar#getInstance)并使用静态方法调用直接构造(new Date()),如:

long time = SystemTime.asMillis();
Calendar calendar = SystemTime.asCalendar();
Date date = SystemTime.asDate();
Run Code Online (Sandbox Code Playgroud)

假冒时间你只需要修改SystemTime类返回的内容.
SystemTime使用默认委托给System.currentTimeMillis()的TimeSource接口

public interface TimeSource {
    long millis();
}
Run Code Online (Sandbox Code Playgroud)

可配置的SystemTime实现可能是这样的

public class SystemTime {
    private static final TimeSource defaultSrc =
            new TimeSource() {
                public long millis() {
                    return System.currentTimeMillis();
                }
            };

    private static TimeSource source = null;
    public static long asMillis() {
        return getTimeSource().millis();
    }

    public static Date asDate() {
        return new Date(asMillis());
    }
    public static void reset() {
        setTimeSource(null);
    }
    public static void setTimeSource(TimeSource source) {
        SystemTime.source = source;
    }
    private static TimeSource getTimeSource() {
        return (source != null ? source : defaultSrc);
    }
}
Run Code Online (Sandbox Code Playgroud)

并伪造你刚刚做的返回时间

@Test
public void clockReturnsFakedTimeInMilliseconds() throws Exception {
    final long fakeTime = 123456790L;
    SystemTime.setTimeSource(new TimeSource() {
        public long millis() {
                return fakeTime;
        }
    });
    long clock = SystemTime.asMillis();
    assertEquals("Should return fake time", fakeTime, clock);
}
Run Code Online (Sandbox Code Playgroud)

Joda-Time库简化了Java中日期的使用,并为您提供开箱即用的功能