2013-07-30 25 views
9

Tôi đang thử nghiệm một lớp trừu tượng và Mockito không khởi tạo biến thành viên của tôi. Đây là một ví dụ đơn giản để cho bạn thấy vấn đề của tôi.Tại sao Mockito bỏ qua việc khởi tạo biến thành viên của lớp trừu tượng của tôi

Đây là một lớp trừu tượng mà khởi 'lĩnh vực' thành viên:

import java.util.ArrayList; 
import java.util.Collection; 

public abstract class Foo { 
    private final Collection field = new ArrayList(); 

    protected Foo() { 
     System.out.println("In constructor"); 
    } 

    public boolean isNull(Object o) { 
     field.add(o); 

     return o == null; 
    } 

    abstract void someAbstractMethod(); 
} 

Ở đây, lớp thử nghiệm:

import org.junit.Assert; 
import org.junit.Test; 
import org.mockito.Mockito; 

public class FooTest { 
    @Test 
    public void testSomething() { 
     final Foo foo = Mockito.mock(Foo.class); 

     Mockito.when(foo.isNull(Mockito.anyObject())).thenCallRealMethod(); 

     Assert.assertFalse(foo.isNull("baaba")); 
    } 
} 

Khi thử nghiệm đang chạy nó ném một NPE vì lĩnh vực biến ' 'không được khởi tạo!

Tôi đang làm gì sai?

+0

Sử dụng http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html#thenCallRealMethod%28%29 không được khuyến nghị. Bạn muốn kiểm tra cái gì? Nếu nó là việc thực hiện một số phương pháp của Foo, sau đó chỉ cần tạo một lớp con. Sử dụng Mockito, khi bạn muốn xác minh các cuộc gọi phương thức hoặc hành vi. –

+0

Như tôi đã nói với [@ david-wallace] (http://stackoverflow.com/users/1081110/david-wallace), tôi muốn kiểm tra lớp trừu tượng. Ý định của tôi về sử dụng một mô hình là để ngăn chặn lỗi biên dịch nên lớp trừu tượng, hoặc một trong các giao diện của nó, thay đổi. – Pigelvy

Trả lời

4

Đây là hành vi được mong đợi, khi bạn mô phỏng nội dung được tạo là mô hình hoàn chỉnh, do đó, không có ý nghĩa khi khởi tạo các trường là hành vi mặc định. Bên cạnh đó, các trường có thể được khởi tạo bởi một hàm tạo trong các lớp cụ thể hoặc trừu tượng, khi việc khởi tạo mocks bỏ qua constructor đơn giản vì nó là một mô hình, thậm chí còn vô lý hơn khi khởi tạo chúng.

Cố gắng gọi phương thức thực thường là sai khi sử dụng mocks. Thay vào đó, một trong những nên stub hành vi của mô hình.

Mockito.when(foo.isNull(Mockito.anyObject())).thenReturn(false); 
Assert.assertFalse(foo.isNull("baaba")); // assertion always passing 

Tôi không biết trường hợp sử dụng thực tế của bạn nhưng có thể bạn muốn mô phỏng một phần, với spy. Mặc dù nó vẫn được coi là thực hành tồi vì nó thường có nghĩa là bạn cần phải cấu trúc lại mã để sử dụng bố cục.

+0

Tôi dự kiến ​​Mockito sẽ làm điều gì đó mà nó không được thiết kế để làm. Như đã thảo luận với [@ David-Wallace] (http://stackoverflow.com/users/1081110/david-wallace), tôi sẽ tạo ra việc triển khai giả trong các thử nghiệm của tôi, tôi sẽ phải duy trì các phương thức được thêm vào/gỡ bỏ. Thx – Pigelvy

+0

Đây có phải là hành vi mong đợi đối với các thành viên tĩnh không? Tôi đã thử và Mockito yêu cầu các thành viên tĩnh phải được khởi tạo, nên bỏ qua việc khởi tạo đó cũng đúng không? – dushyantashu

+0

@dushyantashu thành viên tĩnh được khởi tạo bởi trình nạp lớp khi lớp được tải. Mockito không thay đổi điều đó. – Brice

3

Bạn dường như đang chế nhạo lớp mà bạn đang thực sự cố gắng kiểm tra. Đó không thực sự là ý tưởng chế giễu. Bạn mô phỏng các lớp nằm ngoài phạm vi kiểm tra của bạn và để lại thứ mà bạn đang thử nghiệm không bị khóa.

Trong trường hợp này, bạn có thể chỉ cần tạo một Foo, với việc triển khai giả là someAbstractMethod và kiểm tra trực tiếp. Không cần cho bất kỳ chế giễu nào, theo như tôi thấy.

+0

Thật vậy, tôi muốn thử lớp trừu tượng tôi đang thử nghiệm để các kiểm tra sẽ không thành công bất cứ khi nào một phương thức trừu tượng mới được thêm vào lớp đó (hoặc một trong các giao diện của nó). Đó thực sự là một thực hành tồi? – Pigelvy

+0

Tôi không đủ kinh nghiệm để đặt ra luật về "hành vi xấu" là gì và những gì không phải là. Nhưng nó cảm thấy khá giống như sử dụng một cái đục như một tuốc nơ vít. Nó không phải là những gì mocks được thiết kế cho.Bản năng của tôi sẽ chỉ gắn bó với việc kiểm tra việc triển khai giả của riêng bạn và thêm các phương thức mới ở mọi nơi mà họ cần. Tôi đoán nó phụ thuộc vào mức độ thường xuyên bạn muốn thêm một phương thức trừu tượng mới vào lớp - nếu đó là một sự xuất hiện thường xuyên, thì điểm của Brice về việc tái cấu trúc để sử dụng bố cục có thể áp dụng. Câu trả lời cho câu hỏi của bạn mặc dù là Mockito không bao giờ có ý định ... –

+0

... các trường khởi tạo trong mocks của nó; bây giờ được trang bị kiến ​​thức đó, hãy tiếp tục và làm thử nghiệm của bạn theo bất kỳ cách nào phù hợp với bạn nhất. –

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