@Mock、@MockBean 和 Mockito.mock() 之间的区别

新手上路,请多包涵

在创建测试和模拟依赖项时,这三种方法有什么区别?

  1. @MockBean:
    @MockBean
   MyService myservice;

  1. @嘲笑:
    @Mock
   MyService myservice;

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

原文由 Doug 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

普通的 Mockito 库

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

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

来自 Mockito 库,在功能上是等效的。

它们允许模拟类或接口并记录和验证其行为。

使用注释的方式更短,因此更可取,而且通常更受欢迎。


请注意,要在测试执行期间启用 Mockito 注释,必须调用 MockitoAnnotations.initMocks(this) 静态方法。

为避免测试之间的副作用,建议在每次测试执行之前进行:

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

启用 Mockito 注释的另一种方法是使用 @RunWith 注释测试类,方法是指定 MockitoJUnitRunner 执行此任务以及其他有用的事情:

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


Spring Boot 库包装 Mockito 库

这确实是一个 Spring Boot 类

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

该类包含在 spring-boot-test 库中。

它允许在 Spring 中添加 Mockito 模拟 ApplicationContext

如果上下文中存在与声明的类兼容的 bean,它会用 mock 替换 它。

如果不是这种情况,它 会将 模拟作为 bean 添加到上下文中。

Javadoc 参考:

可用于将模拟添加到 Spring ApplicationContext 的注释。

如果上下文中定义的任何现有的相同类型的单个 bean 将被模拟替换,如果没有定义现有的 bean,则将添加一个新的。


何时使用经典/普通 Mockito 以及使用 Spring Boot 中的 @MockBean 时?

单元测试旨在独立于其他组件来测试一个组件,并且单元测试还有一个要求:在执行时间方面尽可能快,因为这些测试可能每天在开发人员机器上执行数十次。

因此,这里有一个简单的指导方针:

当您编写不需要来自 Spring Boot 容器的任何依赖项的测试时,经典/普通的 Mockito 是遵循的方式:它速度快并且有利于测试组件的隔离。

如果您的测试需要依赖 Spring Boot 容器 ,并且 您还想添加或模拟容器 bean 之一:来自 Spring Boot 的 @MockBean 是一种方式。


Spring Boot的典型用法 @MockBean

当我们编写一个用 @WebMvcTest (网络测试切片)注释的测试类时。

Spring Boot 文档 很好地总结了这一点:

通常 @WebMvcTest 将被限制为单个控制器,并与 @MockBean 结合使用,为所需的协作者提供模拟实现。

这是一个例子:

 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"));
    }

}

原文由 davidxxx 发布,翻译遵循 CC BY-SA 3.0 许可协议

最后很容易解释。如果您只查看注释的 javadoc,您将看到不同之处:

@模拟:( org.mockito.Mock

将字段标记为模拟。

  • 允许速记模拟创建。
  • 最大限度地减少重复的模拟创建代码。
  • 使测试类更具可读性。
  • 使验证错误更易于阅读,因为字段名称用于标识模拟。

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

可用于将模拟添加到 Spring ApplicationContext 的注释。可用作类级别注释或在 @Configuration 类或测试类中的字段 @RunWith SpringRunner。

模拟可以按类型或 bean 名称注册。上下文中定义的任何现有的相同类型的单个 bean 将被模拟替换,如果没有定义现有的 bean,将添加一个新的 bean。

@MockBean 在一个字段上使用时,以及在应用程序上下文中注册时,模拟也会被注入到该字段中。

Mockito.模拟()

它只是 @Mock 的表示。

原文由 Patrick 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题