2010-08-11 25 views
14

Tôi đang sử dụng thử nghiệm đơn vị cho một số lớp tiện ích trong dự án tôi đang làm việc và một trong các lớp (chứa thông tin cấp phép) có phương pháp thực hiện một số quyết định dựa trên thời gian hiện tại.Kiểm tra đơn vị xử lý với điều kiện trong thời điểm hiện tại

tức là giấy phép chứa ngày hết hạn và chuỗi giấy phép xác thực ngày đó, nhưng lôgic thực tế để xem liệu giấy phép hết hạn có dựa trên thời gian hiện tại hay không.

public boolean isValid() 
{ 
    return isLicenseStringValid() && !isExpired(); 
} 

public boolean isExpired() 
{ 
    Date expiry = getExpiryDate(); 
    if(expiry == null) { 
     return false; 
    } 

    Date now = new Date(); 

    return now.after(expiry); 
} 

Vì vậy, tôi không biết phải làm gì, vì điều 'Ngày mới()' không phải là tiêu chí tĩnh.

  1. Tôi không nên bận tâm kiểm tra 'isValid' và chỉ cần kiểm tra 'isLicenseStringValid()' và hàm 'getExpiryDate()' riêng biệt?
  2. Tôi có sử dụng khóa cấp phép trong thử nghiệm với thời gian hết hạn điên rồ như vậy mà tôi sẽ chuyển sang công việc vào thời điểm hết hạn không?
  3. Tôi có cố gắng thử 'Ngày mới()' với phương thức 'getCurrentTime()' để tôi có thể giả mạo thời gian hiện tại không?

Người khác thường làm gì với các thử nghiệm có điều kiện thời gian?

+0

BTW, tôi thấy một vấn đề trong mã của bạn khác so với ngày logic: if (hết hạn == null) { return false; } Tôi không nghĩ bạn nên trả về 'false' trên phương thức' isExpired() 'nếu ngày hết hạn là null. Để biết thêm thông tin, hãy đọc - https://www.owasp.org/index.php/Fail_securely – Garbage

+0

Đó là một đối tượng có giấy phép có hai chế độ có thể: 1. vĩnh viễn không có ngày hết hạn (do đó ở trên) 2. tạm thời với ngày hết hạn vì vậy, chính xác là nếu không có ngày hết hạn được đặt, nó sẽ không hết hạn. –

Trả lời

23

Chắc chắn giả lập new Date().

Tạo giao diện Clock với phương thức getCurrentTime() hoặc tương tự. Bằng cách đó bạn có thể có một FakeClock để thử nghiệm và SystemClock sử dụng System.currentTimeMillis() hoặc bất kỳ thứ gì.

Tôi đã thực hiện việc này một số lần - nó hoạt động rất tốt. Đó là hợp lý quá - hiệu quả bạn yêu cầu một "dịch vụ thời gian hiện tại" do đó cần được tiêm giống như bất kỳ sự phụ thuộc khác.

+0

Cảm ơn, nó cảm thấy một chút kỳ lạ bằng cách sử dụng DI cho những thứ mà cảm thấy giống như một phần của ngôn ngữ chính nó, nhưng nó có vẻ như điều này sẽ làm việc. –

5

Tôi thường đưa nhà cung cấp ngày vào mã được thử nghiệm. Điều này cũng giúp ích nếu bạn cần chuyển đổi các quy ước hay cách khác là "sửa" mã kiểm tra thời gian.

2

Sử dụng bơm phụ thuộc và tiêm TimeProvider cung cấp phương thức getExpiryDate().

1

Cả ba cách tiếp cận có thể xảy ra:

  1. không kiểm tra: lười biếng của con người cách
  2. sử dụng một giấy phép mà sẽ không hết hạn cho các lứa tuổi cho đến khi bạn đã rời khỏi công việc: bao gồm cách ass của tôi
  3. sử dụng một mô hình cho ngày hiện tại, chẳng hạn như một TimeProvider: cách cầu toàn

tôi muốn đi cho một comprimise: tôi muốn thêm ngày hiện tại như một tham số cho phương thức isExpired, và isValid phương pháp. Đối với mã sản xuất trực tiếp của bạn, thêm isValid() ghi đè no-arg đơn giản gọi số isValid(new Date()). Mã thử nghiệm của bạn sử dụng phiên bản lấy ngày hiện tại làm tham số.

+0

Tùy chọn này tôi thích nhất. Nếu ngôn ngữ hỗ trợ mặc định args, nó làm cho nó dễ dàng hơn một chút. – elias

2

Nếu bạn cảm thấy trừu tượng TimeProvider/Clock là quá quá nhiệt tình cầu toàn (mà rất có thể là trường hợp), xem xét việc này thay vì

Hãy getCurrentType bảo vệ ảo, sau đó tạo ra một decendant TestingProductionType của ProductionType có chứa mã Bạn đã đăng.Trong kiểu đó, ghi đè phương thức getCurrentType() để trả về một số kết quả xác định. Trong thử nghiệm đơn vị của bạn, tạo một thể hiện của TestingProductionType này thay thế.

Viola, sự phụ thuộc của thời gian hiện tại hiện đã bị xóa khỏi các thử nghiệm đơn vị của bạn. Mã sản xuất duy nhất hiện không phải là đơn vị được thử nghiệm là một phương thức có một dòng trở về ngày mới(). Tôi có thể sống với điều đó.

2

Nếu bạn có thể xem Mole tại http://research.microsoft.com/en-us/projects/pex/ Moles allows to replace any .NET method with a delegate Chỉ cần sử dụng nó để thay thế Ngày và yêu cầu trả lại số tiền bạn cần. Sau đó, bạn không cần phải làm bất cứ điều gì điên rồ.

-Raul

Các vấn đề liên quan