2009-01-07 25 views
14

Tôi có một lớp mà tôi đang kiểm tra đơn vị với DUnit. Nó có một số phương pháp một số phương pháp công cộng và phương pháp riêng.Làm cách nào để thử nghiệm các phương thức riêng với DUnit?

type 
    TAuth = class(TDataModule) 
    private 
    procedure PrivateMethod; 
    public 
    procedure PublicMethod; 
    end; 

Để viết bài kiểm tra đơn vị cho lớp học này, tôi phải công khai tất cả các phương pháp.

Có cách nào khác để khai báo các phương pháp riêng tư để tôi vẫn có thể kiểm tra chúng nhưng chúng không công khai?

+0

Xem thêm: [Cách thích hợp để kiểm tra một lớp học với các phương thức riêng bằng cách sử dụng JUnit là gì?] (Http://stackoverflow.com/questions/34571/whats-the-proper-way-to-test-a-class -with-private-methods-using-junit) – mjn

+0

Một tùy chọn khác http://stackoverflow.com/questions/7525071/accesing-a-strict-private-field-using-the-rtti – sav

+0

Bản sao có thể có của [Làm cách nào để kiểm tra một lớp học có các phương thức riêng, các trường hoặc các lớp bên trong?] (https://stackoverflow.com/questions/34571/how-do-i-test-a-class-that-has-private-methods-fields-or- bên trong lớp học) – Raedwald

Trả lời

19

Bạn không cần đặt chúng ở chế độ công khai. Được bảo vệ sẽ làm. Sau đó, bạn có thể subtype lớp để kiểm tra đơn vị và bề mặt các phương pháp được bảo vệ. Ví dụ:

type 
    TAuth = class(TDataModule) 
    protected 
    procedure MethodIWantToUnitTest; 
    public 
    procedure PublicMethod; 
    end; 

Bây giờ bạn có thể SUBTYPE nó cho thử nghiệm đơn vị của bạn:

interface 

uses 
    TestFramework, Classes, AuthDM; 

type 
    // Test methods for class TAuthDM 
    TestAuthDM = class(TTestCase) 
    // stuff 
    end; 

    TAuthDMTester = class(TAuthDM) 
    public 
    procedure MethodIWantToUnitTestMadePublic; 
    end; 

implementation 

procedure TAuthDMTester.MethodIWantToUnitTestMadePublic; 
begin 
    MethodIWantToUnitTest; 
end; 

Tuy nhiên, nếu những phương pháp bạn muốn kiểm tra đơn vị đang làm việc rất mật thiết với các module dữ liệu mà nó không phải là an toàn để có chúng bất cứ điều gì nhưng riêng tư, sau đó bạn thực sự nên xem xét tái cấu trúc các phương pháp để tách riêng mã cần phải được kiểm tra đơn vị và mã truy cập vào bên trong của mô-đun dữ liệu.

+2

Yeah mà không có âm quá tiêu cực Tôi không đồng ý với việc làm phương pháp riêng của bạn được bảo vệ vì lợi ích của kiểm tra đơn vị vì chúng là riêng tư vì một lý do. Tôi nghĩ bạn nên thử nghiệm giao diện công cộng. Đó là phương pháp công cộng mà sẽ được sử dụng phương pháp riêng tư của bạn anyway. – CodeAndCats

+1

Tôi (tôn trọng) không đồng ý, vì những lý do tôi giải thích ở đây: http://blogs.teamb.com/craigstuntz/2009/01/12/37919/ –

+1

/Ben: riêng tư và được bảo vệ khác nhau và tất cả đều có giá trị và bất lợi; Nếu bạn muốn e có thể kiểm tra các phương thức riêng tư, làm cho chúng được bảo vệ đơn giản là một cách thô lỗ để làm cho chúng có thể truy cập được vào khung kiểm thử của bạn (DUnit). Điều gì tiếp theo: riêng tư là xấu xa, và nghiêm túc hơn nữa? Tôi đồng ý với Ben: kiểm tra đơn vị là để kiểm tra hợp đồng của bạn (ví dụ giao diện công khai với các quy tắc rõ ràng (giao diện) và rõ ràng (sử dụng)). Nếu các thành viên riêng cần thử nghiệm, bạn nên làm cho giao diện đó chính thức (một phần của giao diện có lẽ, lớp bên trong, v.v.). –

4

Tôi khuyên bạn nên "XUnit Test Patterns" cuốn sách của Gerard Mészáros:

Test-Specific Subclass

Câu hỏi: Làm thế nào chúng ta có thể làm cho mã thể kiểm chứng khi chúng ta cần phải truy cập vào nhà nước riêng của SUT ?

trả lời: Thêm phương pháp lộ tiểu bang hoặc hành vi cần thiết cho kiểm tra để một lớp con của SUT.

... Nếu hệ thống được kiểm tra (SUT) không thiết kế đặc biệt để có thể kiểm chứng, chúng tôi có thể thấy rằng các thử nghiệm không thể có được quyền truy cập vào trạng thái đó nó phải khởi tạo hoặc xác minh tại một số điểm trong sự kiểm tra.

Bài viết cũng giải thích thời điểm sử dụng và rủi ro mà nó mang.

4

Đặt mã DUnit trong đơn vị của bạn. Sau đó, bạn có thể truy cập mọi thứ bạn thích.

+3

... bằng cách sử dụng chỉ thị có điều kiện – too

7

Nó là một chút hacky, nhưng tôi muốn sử dụng chỉ thị này biên soạn có điều kiện:

{$IfNDef TEST} 
    private 
    {$EndIf} 

dự án thử nghiệm đơn vị của bạn nên xác định thử nghiệm trong project → conditional defines.

Không có thông số kỹ thuật hiển thị, chúng sẽ được xuất bản. Cẩn thận: nếu hiển thị riêng tư không phải là người đầu tiên trong khai báo lớp, nó sẽ nhận định nghĩa trước đó.Một cách an toàn hơn, nhưng tiết hơn và ít rõ ràng, sẽ là:

private 
    {$IfDef TEST} 
    public 
    {$EndIf} 

này có một số ưu điểm so với các subclassing hoặc cách tiếp cận khác:

  • Không thêm phức tạp: không có các lớp học thêm trong mã của bạn
  • Không ai có thể "nhầm lẫn" phân lớp và ghi đè lên lớp học của bạn: bạn giữ nguyên kiến ​​trúc của mình
  • Khi bạn nói một phương pháp được bảo vệ, bạn có thể mong đợi rằng nó sẽ bị ghi đè. Bạn đang nói điều này cho những người đang đọc mã của bạn. Một phương pháp được bảo vệ không nên bị ghi đè sẽ gây nhầm lẫn cho người đọc mã của bạn, phá vỡ nguyên tắc lập trình đầu tiên của tôi: "mã phải được viết để được đọc bởi những người khác."
  • DUnit nằm trong đơn vị riêng của chúng, không được bao gồm ở mọi nơi
  • Bạn không chạm vào RTTI lộn xộn.

Tôi nghĩ rằng đó là giải pháp rõ ràng hơn và tốt hơn câu trả lời đã chọn.

Khi tôi sử dụng điều này, tôi cũng định cấu hình dự án thử nghiệm để đặt các đối tượng xây dựng vào một thư mục khác của dự án chính. Điều này ngăn không cho các tệp nhị phân có chỉ thị TEST kết hợp với mã khác.

4

Nói chung, khi tôi gặp phải tình huống này, tôi thường nhận ra rằng tôi đang vi phạm nguyên tắc trách nhiệm duy nhất. Tất nhiên tôi không biết gì về trường hợp cụ thể của bạn, nhưng MAYBE, rằng các phương pháp riêng tư nên ở trong lớp của riêng họ. TAuth sẽ có tham chiếu đến lớp mới này trong phần riêng tư của nó.

1
{$IFNDEF UNITEST} 
private 
{$ENDIF} 

Giải pháp đơn giản, hầu như không phải là hack. Tôi thường xuyên cần phải thử nghiệm phương pháp riêng và kỹ thuật này cho biết thêm ít biến chứng nhất có thể.

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