Sự khác biệt giữa @Mock, @MockBean và Mockito.mock ()


147

Khi tạo các thử nghiệm và phụ thuộc chế giễu, sự khác biệt giữa ba phương pháp này là gì?

  1. @MockBean:

    @MockBean
    MyService myservice;
  2. @Chế nhạo:

    @Mock
    MyService myservice;
  3. Mockito.mock ()

    MyService myservice = Mockito.mock(MyService.class);

Câu trả lời:


197

Thư viện đồng bằng Mockito

import org.mockito.Mock;
...
@Mock
MyService myservice;

import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);

đến từ thư viện Mockito và có chức năng tương đương.
Họ cho phép giả định một lớp hoặc một giao diện và ghi lại và xác minh các hành vi trên đó.

Cách sử dụng chú thích ngắn hơn, vì vậy thích hợp hơn và thường được ưa thích hơn.


Lưu ý rằng để bật chú thích Mockito trong khi thực hiện kiểm tra, MockitoAnnotations.initMocks(this)phương thức tĩnh phải được gọi.
Để tránh tác dụng phụ giữa các lần kiểm tra, nên thực hiện trước mỗi lần thực hiện kiểm tra:

@Before 
public void initMocks() {
    MockitoAnnotations.initMocks(this);
}

Một cách khác để kích hoạt các chú thích Mockito là chú thích lớp kiểm tra bằng @RunWithcách chỉ định MockitoJUnitRunnernhiệm vụ thực hiện nhiệm vụ này và các điều hữu ích khác:

@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}

Thư viện Spring Boot gói thư viện Mockito

Đây thực sự là một lớp Spring Boot :

import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;

Các lớp học được bao gồm trong spring-boot-testthư viện.

Nó cho phép thêm Mockito giả trong một mùa xuân ApplicationContext.
Nếu một bean, tương thích với lớp khai báo tồn tại trong ngữ cảnh, nó sẽ thay thế nó bằng giả.
Nếu nó không phải là trường hợp, nó thêm mock trong bối cảnh như một hạt đậu.

Tham khảo Javadoc:

Chú thích có thể được sử dụng để thêm các giả vào Spring ApplicationContext.

...

Nếu bất kỳ bean đơn hiện có cùng loại được xác định trong ngữ cảnh sẽ được thay thế bằng giả, nếu không có bean nào được xác định thì một bean mới sẽ được thêm vào.


Khi sử dụng Mockito cổ điển / đơn giản và khi sử dụng @MockBeantừ Spring Boot?

Các thử nghiệm đơn vị được thiết kế để kiểm tra một thành phần tách biệt với các thành phần khác và các thử nghiệm đơn vị cũng có một yêu cầu: càng nhanh càng tốt về thời gian thực hiện vì các thử nghiệm này có thể được thực hiện mỗi ngày hàng chục lần trên các máy của nhà phát triển.

Do đó, đây là một hướng dẫn đơn giản:

Khi bạn viết một bài kiểm tra không cần bất kỳ sự phụ thuộc nào từ bộ chứa Spring Boot, Mockito cổ điển / đơn giản là cách để làm theo: nó nhanh và ủng hộ sự cô lập của thành phần được kiểm tra.
Nếu thử nghiệm của bạn cần dựa vào bộ chứa Spring Boot bạn cũng muốn thêm hoặc giả lập một trong những hạt chứa container: @MockBeantừ Spring Boot là cách.


Cách sử dụng điển hình của Spring Boot @MockBean

Khi chúng ta viết một lớp kiểm tra có chú thích @WebMvcTest(lát kiểm tra web).

Tài liệu Spring Boot tóm tắt rất tốt:

Thường @WebMvcTestsẽ được giới hạn trong một bộ điều khiển duy nhất và được sử dụng kết hợp với @MockBeanđể cung cấp các triển khai giả cho các cộng tác viên cần thiết.

Đây là một ví dụ :

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private FooService fooServiceMock;

    @Test
    public void testExample() throws Exception {
         Foo mockedFoo = new Foo("one", "two");

         Mockito.when(fooServiceMock.get(1))
                .thenReturn(mockedFoo);

         mvc.perform(get("foos/1")
            .accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andExpect(content().string("one two"));
    }

}

4
Việc sử dụng @MockBean sẽ tạo một bản sao của bean và đưa nó vào ApplicationContext? Hoặc đậu giả sẽ có tất cả các phương thức của nó là null? Nếu tất cả các phương thức đều rỗng, tôi có thể bỏ chúng như tôi có thể sử dụng @Mock không?
Doug

6
Như đã giải thích, việc sử dụng @MockBeansẽ thay thế bean trong ngữ cảnh ứng dụng nếu một bean khai báo cùng loại đã được xác định trong cấu hình Spring của bạn. Và phép tiêm được thực hiện trong lớp nơi bạn khai báo @MockBean.Các cơ chế DI hoạt động theo cách này: bạn đăng ký một đối tượng trong ngữ cảnh DI và sau đó bạn có thể tiêm đối tượng được tham chiếu trong ngữ cảnh Spring trong một lớp cụ thể. Bạn không tiêm một đối tượng trong bối cảnh DI.
davidxxx

13

Cuối cùng, nó dễ dàng để giải thích. Nếu bạn chỉ nhìn vào javadocs của các chú thích, bạn sẽ thấy sự khác biệt:

@Chế nhạo: (org.mockito.Mock )

Đánh dấu một lĩnh vực là một giả.

  • Cho phép tạo tốc ký giả.
  • Giảm thiểu mã tạo giả lặp đi lặp lại.
  • Làm cho lớp kiểm tra dễ đọc hơn.
  • Làm cho lỗi xác minh dễ đọc hơn vì tên trường được sử dụng để xác định giả.

@MockBean: ( org.springframework.boot.test.mock.mockito.MockBean)

Chú thích có thể được sử dụng để thêm các giả vào Spring ApplicationContext. Có thể được sử dụng như một chú thích cấp lớp hoặc trên các trường trong một trong hai @Configurationlớp hoặc các lớp kiểm tra là @RunWithSpringRunner.

Mocks có thể được đăng ký theo loại hoặc theo tên đậu. Bất kỳ bean đơn hiện có cùng loại được xác định trong ngữ cảnh sẽ được thay thế bằng giả, nếu không có bean nào được xác định, một bean mới sẽ được thêm vào.

Khi @MockBeanđược sử dụng trên một trường, cũng như được đăng ký trong ngữ cảnh ứng dụng, giả cũng sẽ được đưa vào trường.

Mockito.mock ()

Nó chỉ là đại diện của a @Mock.


5
Chúng ta đừng quên rằng @Mock yêu cầu MockitoRunner hoặc initMocks được gọi thủ công.
Florian Schaetz

4
Có phải sự khác biệt duy nhất giữa @MockBean@Mockngười này sẽ tiêm giả vào Spring ApplicationContextngười kia không?
Doug

3
@Doug Bạn đã tóm tắt rất tốt nhưng người ta cần nhớ rằng MockBean là một phần của Spring Boot
comiventor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.