2013-05-06 32 views
5

Tôi có lớp sau:PowerMockito: làm thế nào để giả lập các phương thức được gọi bởi hàm tạo?

public class Foo { 

    public Foo() { 
    initField1(); 
    initField2(); 
    initField3(); 
    } 

} 

tôi cần phải thay đổi hành vi (để thử) initField1()initField3() cho họ làm không phải làm gì hay cái gì khác mà họ thực sự làm. Tôi quan tâm đến việc thực thi mã thực tế của initField2().

Tôi muốn viết bài kiểm tra sau:

Foo foo = new Foo(); 
assertTrue(foo.myGet()); 

myGet() trả về một thuộc tính của Foo đã được tính toán bằng cách initField2(). Tất cả các phương pháp initField() đều là riêng tư

Tôi làm cách nào để thực hiện việc này?

Cảm ơn sự giúp đỡ của bạn và lời chúc mừng tốt đẹp nhất.

Trả lời

-1

Tôi nghĩ có điều gì đó sai trái trong những gì bạn muốn làm.

Theo tôi hiểu, một khung mocking như Mockito hoặc PowerMock có nghĩa là giả lập tương tác giữa đối tượng đang thử nghiệm và các phụ thuộc của nó.

Khi tôi hiểu câu hỏi của bạn, bạn muốn thử một phần của hành vi đối tượng và kiểm tra phần còn lại của hành vi đó.

Trong trường hợp của bạn, bạn muốn kiểm tra cái gì đó sẽ không bao giờ xảy ra, như initField2() sẽ không bao giờ được gọi mà không cần các cuộc gọi đến và initField1()initField3()

Nếu lý do bạn không muốn gọi initField1()initField3 là bởi vì những các phương thức tương tác với các đối tượng khác, hoặc hệ thống tập tin hoặc DB, sau đó bạn nên tiêm các phụ thuộc thông qua đối số constructor hoặc các setters được chú thích, và chỉ cần chèn mocks cho các thử nghiệm của bạn. Và để khởi tạo đối tượng của bạn với các phụ thuộc được thiết lập đúng cách, hãy sử dụng mẫu nhà máy, mẫu xây dựng hoặc thậm chí tốt hơn, sử dụng khung tiêm phụ thuộc như khung từ Spring hoặc Google Guice.

Nếu lý do bạn không muốn gọi initField1()initField3 là vì chúng xử lý logic kinh doanh khác nhau trong đối tượng của bạn, thì mùi này (như trong http://martinfowler.com/books/refactoring.html) như bạn đang vi phạm nguyên tắc trách nhiệm duy nhất và bạn nên cấu trúc lại.

+0

Đây là mã kế thừa. Tôi không muốn sửa đổi lớp đang được kiểm tra bằng cách viết một hàm tạo mới chấp nhận đối số chẳng hạn. Tôi chỉ muốn 'initField2()' được thực thi vì nó chịu trách nhiệm thiết lập trường mà tôi muốn kiểm tra. Tôi không thú vị trong việc kiểm tra phần còn lại của logic của nhà xây dựng. –

+0

Mockito có nghĩa là để giả mạo tương tác, PowerMock có nghĩa là để giả một phần, hoạt động nội bộ của một lớp cho mã di sản, vì vậy câu trả lời này chỉ là đồng bằng sai. – eis

5

Xét bất cứ điều gì có thể xảy ra trong mã di sản :) bạn có thể sử dụng để đàn áp PowerMock phương pháp như mô tả trong http://code.google.com/p/powermock/wiki/SuppressUnwantedBehavior

import static org.powermock.api.support.membermodification.MemberMatcher.methods; 
import static org.powermock.api.support.membermodification.MemberModifier.suppress; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Foo.class) 
public class FooTest { 

    @Test 
    public void testSuppressMethod() throws Exception { 
     suppress(methods(Foo.class, "initField1", "initField3")); 
     Foo foo = new Foo(); 
    } 
} 

Tuy nhiên, bạn nên tái yếu tố lớp sau khi bạn đã có bảo hiểm thử nghiệm đầy đủ cho nó .

+0

Cảm ơn rất nhiều. Nó hoạt dộng bây giờ! Một câu hỏi nữa, làm cách nào để xác minh rằng 'initField2()' được gọi? Tôi nghĩ về việc gián điệp Foo mới của tôi, nhưng thực sự không có sự tương tác với nó nên 'verifyPrivate (foo) .invoke (initField2)' không giúp ích gì. –

+0

@JulienCollah bạn sẽ kiểm tra nó gián tiếp bằng cách kiểm tra 'foo.myGet()' trả về một giá trị đúng. –

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