2012-02-14 58 views
20

Trong mã của tôi, tôi có một cái gì đó như thế này:java: cách mô phỏng Calendar.getInstance()?

private void doSomething() { 
    Calendar today = Calendar.getInstance(); 
    .... 
} 

Làm thế nào tôi có thể "giả" nó trong thử nghiệm junit của tôi để trả lại một ngày cụ thể?

+1

dòng đó không thể được biên dịch! – adarshr

+0

'Hôm nay' là một thành viên lớp (trường) hoặc một biến cục bộ bên trong một phương thức? –

+0

biến cục bộ bên trong một phương thức – Randomize

Trả lời

14

Theo như tôi thấy nó, bạn có ba tùy chọn hợp lý:

  1. Chích Calendar dụ trong bất cứ phương pháp/lớp học mà bạn thiết lập ngày hôm đó ở.

    private void method(final Calendar cal) { Date today = cal.getTime(); }

  2. Sử dụng JodaTime thay vì Calendar. Đây là một lựa chọn ít hơn và nhiều hơn nữa một trường hợp gợi ý như JodaTime sẽ làm cho cuộc sống của bạn dễ dàng hơn nhiều. Bạn vẫn sẽ cần phải tiêm thời gian này vào phương thức.

    DateTime dt = new DateTime();

    Date jdkDate = dt.toDate();

  3. Bọc Calendar bên trong một số giao diện cho phép bạn để lấy thời điểm đó. Sau đó bạn chỉ cần giả lập giao diện đó và làm cho nó trả về hằng số Date.

    Date today = calendarInterfaceInstance.getCurrentDate()

+3

Lớp 'DateTimeUtils' của Joda Time có các phương thức tĩnh đặt thời gian hiện tại cho tất cả các đối tượng Joda Time khác. Điều này rất hữu ích để đặt thời gian vào một thời điểm nhất định, ví dụ như để thử nghiệm. – Jesper

+0

@ Jesper - Vâng, đó là sự thật và một điểm tốt tôi bỏ qua để đề cập đến – BeRecursive

+1

Cảm ơn các bạn. Tôi đã theo gợi ý ur và tôi chuyển đến JodaTime. BTW nó sửa chữa dễ dàng vấn đề với một cái gì đó như: DateTimeUtils.setCurrentMillisFixed (new DateTime (2012, 2, 14, 13, 43, 21) .getMillis()); – Randomize

9

Đừng thử - thay vào đó hãy giới thiệu phương pháp bạn có thể giả lập nhận ngày tháng. Một cái gì đó như thế này:

interface Utility { 

    Date getDate(); 
} 

Utilities implements Utility { 


    public Date getDate() { 

     return Calendar.getInstance().getTime(); 
    } 

} 

Sau đó, bạn có thể tiêm này vào lớp học của bạn hoặc chỉ sử dụng một lớp helper với một loạt các phương pháp tĩnh với một phương pháp tải cho giao diện:

public class AppUtil { 

    private static Utility util = new Utilities(); 

    public static void load(Utility newUtil) { 

     this.util = newUtil; 
    } 

    public static Date getDate() { 

     return util.getDate(); 
    } 

} 

Sau đó, trong ứng dụng của bạn mã:

private void doSomething() { 
    Date today = AppUtil.getDate(); 
    .... 
} 

Sau đó, bạn có thể tải giao diện giả trong phương pháp thử nghiệm của mình.

@Test 
public void shouldDoSomethingUseful() { 
    Utility mockUtility = // .. create mock here 
    AppUtil.load(mockUtility); 

    // .. set up your expectations 

    // exercise the functionality 
    classUnderTest.doSomethingViaAPI(); 

    // ... maybe assert something 

} 

Xem thêm Should you only mock types you own?Test smell - everything is mocked

2

Viết một lớp gọi là DateHelper với một phương pháp getCalendar trả Calendar.getInstance(). Cấu trúc lại lớp mà bạn đang thử nghiệm để nó có một biến thành viên kiểu DateHelper và một hàm tạo để tiêm biến thành viên đó. Sử dụng hàm tạo đó trong thử nghiệm của bạn, để chèn một mô hình DateHelper, trong đó getCalendar đã được đặt lại để trả về một số ngày đã biết.

9

Bạn có thể thử nó bằng cách sử PowerMock kết hợp với Mockito:

Ngày đầu lớp học của bạn:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ClassThatCallsTheCalendar.class}) 

Chìa khóa thành công là bạn phải đặt lớp mà bạn sử dụng Lịch trong PrepareForTest thay vì Lịch vì nó là một lớp hệ thống. (Cá nhân tôi đã phải tìm kiếm rất nhiều trước khi tôi thấy điều này)

Sau đó chế giễu bản thân:

mockStatic(Calendar.class); 
when(Calendar.getInstance()).thenReturn(calendar); 
+0

bạn phụ thuộc vào phương thức nào để có được phương thức mockStatic()? –

+0

Xin lỗi tôi nên nói vậy. Tôi đã sử dụng tính năng nhập tĩnh để nhập phương thức mockStatic của PowerMockito. Xem phụ thuộc này cho mockito powermock: http://mvnrepository.com/artifact/org.powermock/powermock-api-mockito2/1.6.6 – GoGoris

6

Sử dụng Mockito và PowerMockito:

Calendar endOfMarch = Calendar.getInstance(); 
endOfMarch.set(2011, Calendar.MARCH, 27); 
PowerMockito.mockStatic(Calendar.class); 
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch); 

Tham khảo link cho mã hoàn chỉnh.

0

Đối với những người sau MVP mẫu chế giễu Lịch là một miếng bánh:

  1. Trong một Presenter tạo ra một phương thức mà trả dụ lịch:

    public Calendar getCurrentTime() { 
         return Calendar.getInstance();  
        } 
    
  2. Theo quan điểm của bạn (Hoạt động, Phân đoạn, v.v.) bạn truy cập vào lịch với sự trợ giúp của người trình bày:

    Calendar calendar = mPresenter.getCurrentTime(); 
    // do whatever you want 
    
  3. Trong các thử nghiệm của bạn, bạn cần làm:

    // create a dummy calendar 
    Calendar mockCalendar = ... 
    // You've already mocked your Presenter, haven't you? 
    when(mMockPresenter.getCurrentTime()).thenReturn(mockCalendar); 
    // here you are!