2016-03-18 23 views
9

Chuỗi Tôi có một Spring MVC @Controller với constructor này:Tiêm một tài sản với @InjectMocks

@Autowired 
public AbcController(XyzService xyzService, @Value("${my.property}") String myProperty) {/*...*/} 

Tôi muốn viết một bài kiểm tra đơn vị độc lập cho điều khiển này:

@RunWith(MockitoJUnitRunner.class) 
public class AbcControllerTest { 

    @Mock 
    private XyzService mockXyzService; 

    private String myProperty = "my property value"; 

    @InjectMocks 
    private AbcController controllerUnderTest; 

    /* tests */ 
} 

Có cách nào thế nào để có được @InjectMocks để tiêm tài sản String của tôi? Tôi biết tôi không thể giả lập một String vì nó không thay đổi, nhưng tôi có thể chỉ cần tiêm một String bình thường ở đây không?

@InjectMocks chèn một giá trị rỗng theo mặc định trong trường hợp này. @Mock dễ hiểu ném một ngoại lệ nếu tôi đặt nó trên myProperty. Có chú thích nào khác mà tôi đã bỏ lỡ, chỉ có nghĩa là "tiêm đối tượng chính xác này chứ không phải là một mô hình của nó"?

+0

Tôi biết tôi có thể tự khởi tạo bộ điều khiển của tôi theo phương pháp thiết lập, nhưng tôi hy vọng sẽ tìm được giải pháp cho kiểu cấu hình chú thích. Cảm ơn! –

Trả lời

4

Bạn không thể làm điều này với Mockito, bởi vì, như bạn đã đề cập, một Stringfinal và không thể bị nhạo báng.

Có một chú thích @Spy mà hoạt động trên thực đối tượng, nhưng nó có những hạn chế tương tự như @Mock, do đó bạn không thể do thám trên String.

Không có chú thích nào để yêu cầu Mockito chỉ bơm giá trị đó mà không làm bất kỳ việc nhạo báng hoặc gián điệp nào. Nó sẽ là một tính năng tốt, mặc dù. Có lẽ đề nghị nó tại Mockito Github repository.

Bạn sẽ phải tự khởi tạo trình điều khiển của mình nếu bạn không muốn thay đổi mã của mình.

Cách duy nhất để có kiểm tra dựa trên chú thích thuần túy là cấu trúc lại bộ điều khiển. Nó có thể sử dụng một đối tượng tùy chỉnh chỉ chứa một thuộc tính đó, hoặc có thể là một lớp cấu hình với nhiều thuộc tính.

@Component 
public class MyProperty { 

    @Value("${my.property}") 
    private String myProperty; 

    ... 
} 

Điều này có thể được đưa vào bộ điều khiển.

@Autowired 
public AbcController(XyzService xyzService, MyProperty myProperty) { 
    ... 
} 

Bạn có thể thử và tiêm sau đó.

@RunWith(MockitoJUnitRunner.class) 
public class AbcControllerTest { 

    @Mock 
    private XyzService mockXyzService; 

    @Mock 
    private MyProperty myProperty; 

    @InjectMocks 
    private AbcController controllerUnderTest; 

    @Before 
    public void setUp(){ 
     when(myProperty.get()).thenReturn("my property value"); 
    } 

    /* tests */ 
} 

Đây không phải là khá thẳng về phía trước, nhưng ít nhất bạn sẽ có thể có một thử nghiệm dựa trên chú thích thuần túy với một chút bướng bỉnh.

+1

Thật không may. Tôi đã xem xét công cụ vấn đề của mình và có vẻ như họ đã [thảo luận] (https://github.com/mockito/mockito/issues/174) nó [trước] (https://github.com/mockito/mockito/pull/277). Ý tưởng chung dường như là nó nằm ngoài phạm vi cho một khuôn khổ mocking, và thậm chí có thể là một mùi mã, mặc dù tôi không nghĩ rằng tôi đồng ý với điều đó. Cảm ơn sự giúp đỡ của bạn! –

9

Bạn không thể làm điều này với Mockito, nhưng Apache Commons thực sự có cách để thực hiện việc này bằng cách sử dụng một trong các tiện ích tích hợp sẵn. Bạn có thể đặt điều này trong một hàm trong JUnit được chạy sau khi Mockito tiêm phần còn lại của mocks nhưng trước khi các trường hợp thử nghiệm của bạn chạy, như sau:

@InjectMocks 
MyClass myClass; 

@Before 
public void before() throws Exception { 
    FieldUtils.writeField(myClass, "fieldName", fieldValue, true); 
} 
Các vấn đề liên quan