2013-05-06 31 views
7

Tôi đã thực sự nhận được vào TDD và tôi đã bắt đầu sử dụng mockito trong jUnit để cải thiện khả năng kiểm tra mã của tôi. Tôi thực sự yêu mockito!gọi phương thức tĩnh trên tham số mà không instantiating lớp trong đối số

Tôi nhận thấy rằng tôi phải thay đổi cách tôi nghĩ về mã hóa, như chuyển các cộng tác viên càng nhiều càng tốt vào các phương pháp và hạn chế công việc được thực hiện trong các nhà thầu bất cứ khi nào có thể.

Kịch bản sau đây đã đảm bảo một số lời khuyên từ các chuyên gia ở đây về SO.

Giả sử tôi có một phương thức, điều đó sẽ gọi một số phương thức tĩnh trên một lớp nhất định. VÍ DỤ.

public void method(){ 
    OtherClass.staticMethod(); 
} 

Điều này thường rất tệ nhưng cần thiết trong trường hợp của tôi. Để làm cho mã dễ kiểm tra hơn trong các bài kiểm tra đơn vị của tôi, tôi muốn tránh sự phụ thuộc vào OtherClass và chuyển nó thành một đối số.

Điều này không hoạt động vì nó mang lại lỗi thời gian biên dịch.

public void method(Class<? extends OtherClass> util){ 
    util.staticMethod(); 
} 
... 
method(OtherClass.class); 

này sẽ làm việc, nhưng tôi không thích OtherClass instantiating nếu tôi không phải, vì nó là chỉ một lớp các tiện ích tĩnh như phương pháp:

public void method(OtherClass util){ 
    util.staticMethod(); 
} 
... 
method(new OtherClass()); 

Câu hỏi của tôi cho bạn : Có cách nào tốt hơn thích hợp hơn để thực hiện việc này mà không sử dụng từ khóa mới không?

+2

Câu hỏi rất được định dạng cho người dùng mới, xin chúc mừng :) – MarioDS

+0

Tôi không chắc liệu mã cuối cùng của bạn có phải là từ nếu bạn chuyển một thể hiện của một lớp con 'OtherClass'. Việc truy cập các phương thức tĩnh thông qua một cá thể có vẻ khó hiểu với tôi vì nó không liên quan đến cá thể đó ** và nó có thể không hoạt động theo cách bạn nghĩ. –

+0

BTW, sử dụng ** Singleton Pattern ** thay vì phương pháp tĩnh trong trường hợp của bạn? –

Trả lời

0

Trong mẫu mã của bạn:

public void method(){ 
    OtherClass.staticMethod(); 
} 

hiểu biết của tôi là, cần có một số logic trong phương pháp trên ngoài việc gọi phương thức tĩnh, và đó là những gì bạn muốn kiểm tra và không phương pháp tĩnh.

Nếu vậy trong trường hợp này bạn có thể viết thực hiện mô hình OtherClass.staticMethod hoặc sẽ bỏ qua tất cả logic hoặc sẽ trả lại giá trị mong muốn hoặc thực hiện logic cụ thể. Điều này sẽ tránh sự phụ thuộc vào OtherClass và cung cấp cho kiểm tra kiểm soát rõ ràng trên đó.

0

Bạn có thể sử dụng phương pháp đầu tiên của bạn bằng cách thay đổi phương pháp của bạn như thế này

public void method(Class<? extends OtherClass> clazz) throws Exception { 
    Method[] mArray = clazz.getMethods(); 
    for(Method m :mArray) { 
     if(!m.isAccessible()) m.setAccessible(true); 
     if((m.getModifiers() & Modifier.STATIC) != 0) { // Here a method which is static is executed. You can change this condition, to suit your needs 
      m.invoke(null); 
     } 
    } 
} 

Và bạn có thể gọi nó bằng cách gọi

method(OtherClass.class); 

mà không cần đi qua một đối tượng mới của lớp đó

0

Bạn có thể sử dụng phản chiếu:

// exceptions management omitted 
public void method(Class<? extends OtherClass> clazz, String methodName) { 
    // methodName could also be a constant if it won't change 
    clazz.getMethod(methodName).invoke(null); 
} 

Sau đó,

method(OtherClass.class, "staticMethod"); 
0

Dưới đây là những gì tôi chỉ cố gắng:

public void testMethod(Class<T> clazz) throws Exception{   
     Method m = clazz.getMethod("staticMethod",null); 
     m.invoke(null,null); 
    } 

Tôi giả định (như đã đề cập trong ví dụ của bạn) rằng phương pháp tĩnh không có bất kỳ cuộc tranh cãi.

Vui lòng tham khảo các tài liệu của các phương pháp getMethod()inovke().

0

Không có gì sai trong một chút mã tĩnh ở đây và ở đó - nếu nó không truy cập vào một trạng thái toàn cầu:

Nếu mã tĩnh hoàn toàn là thủ tục

public void method(){ 
    OtherClass.staticMethod(); 
} 

Bạn có thể giả lập nó xung quanh phương thức(), miễn là bạn giữ cuộc gọi tĩnh là thao tác duy nhất trong phương thức

Khác nếu phương pháp tĩnh của bạn bảo vệ một số trạng thái toàn cục, bạn sẽ tốt hơn off với một Singleton + Locator

public class Registry { 
    DoSomethingInterface getOtherClass() { 
     return OtherClass.getSingleton(); 
    } 
} 


public void method(Registry reg){ 
    reg.getOtherClass().doSomething(); 
} 

sau đó bạn có thể phân lớp registry để cung cấp tất cả các loại biến thể đến getOtherClass() định vị, vì vậy bạn có thể có một TestRegistry instantiated vào những thời điểm thử nghiệm chăm sóc cung cấp trạng thái toàn cầu sạch sẽ và những thứ khác

Nếu bạn vẫn cần lớp khác là tĩnh vì bạn không thể thay đổi nó theo bất kỳ cách nào (ví dụ: thư viện lớp), bạn có thể bọc nó trong giao diện của bạn:

public class Registry { 
    DoSomethingInterface getOtherClass() { 
     return new DoSomethingInterface(){ 
      public void doSomething() { 
       OtherClass.staticMethod(); 
      } 
     }; 
    } 
} 
1

này sẽ làm việc, nhưng tôi không thích OtherClass instantiating nếu tôi không phải, vì nó là chỉ một lớp của tiện ích tĩnh như phương pháp:

public void method(OtherClass util){ 
    util.staticMethod(); 
} 
... 
method(new OtherClass()); 

Trên thực tế, điều này không làm việc, vì nó sẽ luôn luôn gọi thực hiện phương pháp từ OtherClass, không phụ thuộc vào đối tượng bạn vượt qua (ngay cả khi bạn vượt qua 0.123.).

Tôi khuyên bạn không nên sử dụng sự phản chiếu để đơn giản hóa việc kiểm tra, vì điều này bỏ qua việc kiểm tra thời gian biên dịch (không được trình biên dịch phát hiện sai) và ngăn không cho sử dụng nhiều tính năng của IDE , javadoc hovers, hỗ trợ tái cấu trúc, hiển thị phân cấp cuộc gọi, chuyển đến định nghĩa, ...)

Cách tiếp cận phổ biến là sử dụng công văn đa hình. Trong Java, điều này yêu cầu phương thức không tĩnh và không phải là riêng tư. Quy tắc của ngón tay cái do đó là: Nếu nó cần chế nhạo, nó không nên tĩnh.

Cách tốt nhất để có được cá thể đối tượng tùy thuộc vào hoàn cảnh của bạn; tiêm phụ thuộc (cách tiếp cận của bạn), mẫu định vị tài nguyên và mẫu đơn lẻ đều có những ưu điểm và nhược điểm riêng.

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