2008-09-30 24 views
34

Tôi mới sử dụng đối tượng giả, nhưng tôi hiểu rằng tôi cần phải có các lớp của mình triển khai các giao diện để giả lập chúng.Làm thế nào để giả lập với các phương pháp tĩnh?

Sự cố tôi gặp phải là trong lớp truy cập dữ liệu của mình, tôi muốn có các phương pháp tĩnh, nhưng tôi không thể đặt phương thức tĩnh trong giao diện.

Cách tốt nhất để giải quyết vấn đề này là gì? Tôi có nên chỉ sử dụng phương pháp dụ (mà có vẻ sai) hoặc là có một giải pháp?

Trả lời

22

Tôi sẽ sử dụng mẫu đối tượng phương thức. Có một trường hợp tĩnh này, và gọi nó trong phương thức tĩnh. Nó có thể được phân lớp để thử nghiệm, tùy thuộc vào khuôn khổ mocking của bạn.

tức là trong lớp học của bạn bằng phương pháp tĩnh có:

private static final MethodObject methodObject = new MethodObject(); 

public static void doSomething(){ 
    methodObject.doSomething(); 
} 

và đối tượng phương pháp của bạn có thể là một rất đơn giản, dễ dàng thử nghiệm:

public class MethodObject { 
    public void doSomething() { 
     // do your thang 
    } 
} 
+0

Bạn có bất kỳ tham chiếu nào tốt cho mẫu đó không? Tôi không chắc tôi sẽ làm thế nào. – brien

+0

Err, không thực sự. Tôi không chắc liệu tôi có tạo ra cái tên đó hay không, hay nó được coi là thành ngữ hơn là một khuôn mẫu, nhưng tôi không thể thấy bất kỳ tài liệu tham khảo phong nha nào của Google. Sẽ tiếp tục tìm kiếm mặc dù. – Grundlefleck

+1

Cảm ơn, ví dụ đã giúp tôi hiểu ý của bạn. – brien

23

Vâng, bạn sử dụng phương pháp dụ . Phương pháp tĩnh về cơ bản nói, "Có một cách để thực hiện chức năng này - nó không phải là đa hình." Mocking dựa trên đa hình. Bây giờ, nếu các phương pháp tĩnh của bạn không quan tâm đến việc bạn đang sử dụng cái gì, chúng có thể lấy các giao diện như các tham số, hoặc có thể làm việc mà không tương tác với trạng thái - nhưng nếu không bạn nên sử dụng các trường hợp (và có thể là sự tiêm phụ thuộc để nối mọi thứ lại với nhau).

4

Sử dụng các phương pháp thể hiện nếu có thể.

Sử dụng công khai tĩnh Func [T, U] (tham chiếu hàm tĩnh có thể được thay thế cho các hàm mô phỏng) trong đó không thể thực hiện các phương pháp mẫu.

5

Bạn có thể đang cố thử nghiệm tại điểm bắt đầu quá sâu. Một thử nghiệm không cần phải được tạo ra để kiểm tra từng phương pháp riêng lẻ; các phương thức riêng và tĩnh cần được kiểm tra bằng cách gọi các phương thức công khai mà sau đó gọi các phương thức riêng và tĩnh.

Vì vậy, cho phép nói rằng mã của bạn là như thế này:

public object GetData() 
{ 
object obj1 = GetDataFromWherever(); 
object obj2 = TransformData(obj1); 
return obj2; 
} 
private static object TransformData(object obj) 
{ 
//Do whatever 
} 

Bạn không cần phải viết một bài kiểm tra so với phương pháp TransformData (và bạn không thể). Thay vào đó hãy viết một bài kiểm tra cho phương thức GetData để kiểm tra công việc được thực hiện trong TransformData.

25

Tôi tìm thấy một blog via google với một số ví dụ tuyệt vời về cách để làm điều này:

  1. Refactor lớp là một lớp dụ và thực hiện một giao diện.

    Bạn đã tuyên bố rằng bạn không muốn thực hiện việc này.

  2. Sử dụng một trường hợp lớp wrapper với các đại biểu cho các lớp học viên tĩnh

    Việc làm này bạn có thể mô phỏng một giao diện tĩnh thông qua các đại biểu.

  3. Sử dụng một lớp dụ wrapper với các thành viên được bảo vệ mà gọi lớp tĩnh

    Đây có lẽ là dễ nhất để thử/quản lý mà không refactoring vì nó chỉ có thể được thừa hưởng từ và mở rộng.

1

Một giải pháp đơn giản là để cho phép thay đổi thực hiện lớp tĩnh của thông qua một setter:

class ClassWithStatics { 

    private IClassWithStaticsImpl implementation = new DefaultClassWithStaticsImpl(); 

    // Should only be invoked for testing purposes 
    public static void overrideImplementation(IClassWithStaticsImpl implementation) { 
    ClassWithStatics.implementation = implementation; 
    } 

    public static Foo someMethod() { 
    return implementation.someMethod(); 
    } 

} 

Vì vậy, trong việc thiết lập các bài kiểm tra của bạn, bạn gọi overrideImplementation với một số giao diện chế giễu. Lợi ích là bạn không cần phải thay đổi các máy khách của lớp tĩnh của bạn. Nhược điểm là bạn có thể sẽ có một chút mã trùng lặp, bởi vì bạn sẽ phải lặp lại các phương thức của lớp tĩnh và nó thực hiện. Nhưng một số lần các phương pháp tĩnh có thể sử dụng một giao diện ligther cung cấp tính cơ bản.

+3

Chỉ cần một điểm nhỏ, sẽ không thực hiện phải được khai báo tĩnh nếu nó được truy cập một cách tĩnh? – Grundlefleck

0

Sự cố bạn gặp phải khi bạn đang sử dụng mã của bên thứ 3 và được gọi từ một trong các phương pháp của bạn. Những gì chúng tôi đã kết thúc làm là gói nó trong một đối tượng, và gọi đi qua nó với dep inj, và sau đó thử nghiệm đơn vị của bạn có thể giả lập phương pháp tĩnh bên thứ 3 gọi setter với nó.

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