@RunWith(SpringRunner.class)vs @RunWith(MockitoJUnitRunner.class)

时间:2018-04-03 16:54:40

标签: junit mockito spring-test

我使用@RunWith(MockitoJUnitRunner.class)进行了与mockito的junit测试。但现在我正在使用spring boot app并尝试使用@RunWith(SpringRunner.class)。使用@RunWith(SpringRunner.class)比使用@RunWith(MockitoJUnitRunner.class)有什么优势吗?我仍然可以使用@Injectmock@Mock@Spy@RunWith(SpringRunner.class)

等功能

5 个答案:

答案 0 :(得分:14)

SpringRunner支持将Spring ApplicationContext和bean @Autowired加载到测试实例中。 它确实比它更多(在Spring参考手册中有所介绍),但这是基本的想法。

然而,MockitoJUnitRunner支持使用Mockito创建模拟和间谍。

但是,对于JUnit 4,您一次只能使用一个Runner

因此,如果你想同时使用Spring和Mockito的支持,你只能选择一个的那些跑步者。

但是你很幸运,因为除了 runners 之外,Spring和Mockito都提供规则

例如,您可以使用带有Mockito规则的Spring runner,如下所示。

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {

    @Rule
    public MockitoRule rule = MockitoJUnit.rule();

    @Mock
    MyService myService;

    // ...
}

但是,通常,如果您正在使用Spring Boot并且需要从Spring ApplicationContext模拟 bean ,那么您将使用Spring Boot' s {{1支持而不仅仅是@MockBean

答案 1 :(得分:4)

当使用SpringRunner.class时,Spring提供相应的注释:

  • @MockBean
  • @SpyBean

通过@Autowired注释将模拟注入到测试对象中。要启用此功能,必须使用

注释测试
  • @SpringBootTest

  • @TestExecutionListeners(MockitoTestExecutionListener.class)

更多详细信息和示例可在官方文档中找到:Mocking and Spying Beans

答案 2 :(得分:2)

根据JavaDoc:

  

SpringRunner是SpringJUnit4ClassRunner的别名。   要使用此类,只需用@RunWith(SpringRunner.class)注释基于JUnit 4的测试类即可。   如果您想将Spring TestContext框架与其他运行程序一起使用,请使用org.springframework.test.context.junit4.rules.SpringClassRuleorg.springframework.test.context.junit4.rules.SpringMethodRule

还有TestContext的JavaDoc:

  

TestContext封装了执行测试的上下文,而与使用的实际测试框架无关。

方法getApplicationContext()的方法:

  

获取此测试上下文的应用程序上下文,可能已缓存。   如果尚未加载相应的上下文,则此方法的实现负责加载应用程序上下文,并可能还会缓存该上下文。

因此,SpringRunner确实加载了上下文并负责维护它。例如,如果要将数据持久存储到嵌入式数据库(例如H2内存数据库)中,则必须使用SpringRunner.class;并且,要清理表以摆脱每次测试后插入的记录,请用@DirtiesContext注释测试以告知Spring进行清理。

但是,这已经是集成或组件测试。如果您的测试是纯单元测试,则不必加载数据库,或者您只想验证某种依赖项方法(MockitoJUnit4Runner就足够了)。您可以随意使用@MockMockito.verify(...),然后测试就会通过。而且速度更快。

测试应该很快。尽可能快地。因此,请尽可能使用MockitoJUnit4Runner加快速度。

答案 3 :(得分:1)

场景2019年11月:春季启动:2.1.1。发布

  • 您有一个Spring Boot api支架
  • 您需要测试名为 MySuperSpringService
  • 的服务
  • 但是,在MySuperSpringService内部,还需要两个自动接线。一种是执行sql select( MyJpaRepository ),另一种是调用外部api rest( MyExternalApiRest
@Service
public class MySuperSpringService {

  @Autowired
  private MyRepository innerComponent1;

  @Autowired
  private MyExternalApiRest innerComponent2;

  public SomeResponse doSomething(){}
}

如何测试MySuperSpringService模拟数据库和外部api rest?

因此,为了测试该服务 MySuperSpringService ,该服务需要另一个spring bean:MyJpaRepository和MyExternalApiRest,您需要使用 @MockBean 对其进行模拟并在您创建结果时需要。

import static org.mockito.Mockito.when;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;

import junit.framework.TestCase;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = your.package.Application.class)
public class MySuperSpringServiceTest extends TestCase {

  @Autowired
  private MySuperSpringService serviceToTest;

  @MockBean
  private MyRepository myRepository;

  @MockBean
  private MyExternalApiRest myExternalApiRest;

  @Before
  public void setUp()  {

    Object myRepositoryResult = new Object();
    //populate myRepositoryResult as you need
    when(myRepository.findByClientId("test.apps.googleusercontent.com"))
        .thenReturn(myRepositoryResult);

    Object myExternalApiRestResult = new Object();
    //populate myExternalApiRestResult as you need
    when(myExternalApiRest.listUserRoles("john@doe.com")).thenReturn(myExternalApiRestResult);

  }

  @Test
  public void testGenerateTokenByGrantTypeNoDatabaseNoGoogleNoSecurityV1(){
    SomeResponse response = serviceToTest.doSomething();
    //put your asserts here
  }

}

答案 4 :(得分:0)

您绝对可以将SpringRunner用于单元测试和集成测试。 SpringRunner Tutorial