2012-12-28 28 views
10

Tôi cần kiểm tra phương thức handleIn() bằng Mockito.Mockito bỏ qua phương pháp tĩnh để thử nghiệm

Tuy nhiên, mã cần gọi mã di sản này Util.getContextPDO là phương pháp tĩnh.

Lưu ý rằng trong môi trường thử nghiệm, Util.getContextPDO này luôn trả về Ngoại lệ và tôi định bỏ qua Util.getContextPDO() này bằng cách trả về một IPDO giả.

public class MyClass { 
    public IPDO getIPDO() 
    { 
    return Util.getContextPDO(); // note that Util.getContextPDO() is a static, not mockable. 
    } 

    public String handleIn(Object input) throws Throwable 
    { 
    String result = ""; 
    IPDO pdo = getIPDO(); 

    // some important business logic. 

    return result; 
    } 
} 

Ban đầu tôi nghĩ điều này có thể đạt được bằng cách sử dụng gián điệp() của lớp "MyClass", vì vậy tôi có thể thử giá trị trả về của getIPDO(). Dưới đây là nỗ lực ban đầu của tôi sử dụng gián điệp()

@Test 
public void testHandleIn() throws Exception 
{ 
    IPDO pdo = new PDODummy(); 


    MyClass handler = new MyClass(); 
    MyClass handler2 = spy(handler); 

    when(handler2.getIPDO()).thenReturn(pdo); 
    PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123"); 
    IPDO pdoNew = handler2.getIPDO(); 

    Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY))); 

} 

Tuy nhiên khi (handler2.getIPDO()) thenReturn (PDO). là ném ngoại lệ mà tôi muốn tránh (vì handler2.getIPDO()) dường như gọi phương thức thực.

Bất kỳ ý tưởng nào về cách kiểm tra phần mã này?

+0

Chúng tôi đang sử dụng ** PowerMock ** cùng với ** Mockito ** để kết hợp với di sản. Điều này trở nên dễ dàng vì vậy chúng tôi đã thực hiện quy tắc để tránh ** PowerMock ** để chiến đấu với di sản hiệu quả hơn –

+1

Sự cố "duy nhất" với PowerMock là bạn buộc phải sử dụng nhân tố thử nghiệm riêng của mình, không phải lúc nào cũng là một tùy chọn (khi viết Ví dụ, các cuộc kiểm tra Robolectric trên Android đòi hỏi người chạy robot riêng của họ) –

Trả lời

10

thay đổi thử nghiệm của tôi để:

@Test 
public void testHandleIn() throws Exception 
{ 
    IPDO pdo = new PDODummy(); 


    MyClass handler = new MyClass(); 
    MyClass handler2 = spy(handler); 

    doReturn(pdo).when(handler2).getIPDO(); 
    PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123"); 
    IPDO pdoNew = handler2.getIPDO(); 

    Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY))); 

} 

Giải Quyết sau khi đọc Effective Mockito.

+2

"Vấn đề" với gián điệp, rằng phương pháp thực tế được gọi trong khi đang cố định. Cách duy nhất để tránh điều này là sử dụng biểu mẫu doXXXX.when (mock) .somemethod (anyParam()). –

11

Một kỹ thuật tốt để loại bỏ các cuộc gọi tĩnh trên API của bên thứ ba đang ẩn cuộc gọi tĩnh phía sau giao diện.

Hãy nói rằng bạn thực hiện giao diện này:

interface IPDOFacade { 

    IPDO getContextPDO(); 
} 

và có một thực hiện mặc định mà chỉ đơn giản gọi phương thức tĩnh trên API bên thứ 3:

class IPDOFacadeImpl implements IPDOFacade { 

    @Override 
    public IPDO getContextPDO() { 
     return Util.getContextPDO(); 
    } 
} 

Sau đó, nó chỉ đơn giản là một vấn đề tiêm sự phụ thuộc trên giao diện vào MyClass và sử dụng giao diện, thay vì API của bên thứ 3 trực tiếp:

public class MyClass { 

    private final IPDOFacade ipdoFacade; 

    public MyClass(IPDOFacade ipdoFacade) { 
     this.ipdoFacade = ipdoFacade; 
    } 

    public String handleIn(Object input) throws Throwable 
    { 
     String result = ""; 
     IPDO pdo = getIPDO(); 

     someImportantBusinessLogic(pdo); 

     return result; 
    } 

    ... 

} 

Trong thử nghiệm đơn vị của bạn, sau đó bạn có thể dễ dàng thử giao diện của riêng bạn, làm cho nó bất kỳ cách nào bạn thích và tiêm nó vào đơn vị được thử nghiệm.

này

  • tránh sự cần thiết để thực hiện các phương pháp gói tin riêng.
  • làm cho các bài kiểm tra của bạn dễ đọc hơn bằng cách tránh chế nhạo từng phần.
  • áp dụng đảo ngược kiểm soát.
  • tách riêng ứng dụng của bạn khỏi thư viện của bên thứ ba cụ thể.
+0

Bây giờ, làm thế nào để bạn viết một bài kiểm tra đơn vị cho IPDOFacadeImpl.getContextPDO()? – aquacode

+0

Bạn không, bạn viết một bài kiểm tra tích hợp cho nó. – bowmore

+0

Câu trả lời hay. Đây là mã/tệp nhiều hơn, nhưng cảm thấy đúng. Nó cho phép bạn tránh các gián điệp (mà Mockito nói để tránh), cho phép bạn tránh các cảnh báo về cách gọi các phương thức tĩnh trên các đối tượng thể hiện, và tuân thủ IoC. – Marquee

1
when(handler2.getIPDO()).thenReturn(pdo); 

thực sự sẽ gọi phương thức và sau đó trở pdo không phân biệt.

Trong đó:

doReturn(pdo).when(handler2).getIPDO(); 

Sẽ trở lại PDO mà không gọi phương thức getIPDO().

+0

vẫn còn với doReturn và khi phương thức tĩnh sẽ được gọi. – Dish

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