【问题标题】:How to use Mockito with JUnit5如何在 JUnit5 中使用 Mockito
【发布时间】:2017-04-19 01:36:39
【问题描述】:

如何在 Mockito 和 JUnit 5 中使用注入?

在 JUnit4 中,我可以只使用 @RunWith(MockitoJUnitRunner.class) 注释。在JUnit5中是没有@RunWith注解?

【问题讨论】:

    标签: java unit-testing mockito junit5


    【解决方案1】:

    有多种使用 Mockito 的方法 - 我将一一介绍。

    手动

    使用Mockito::mock 手动创建模拟无论 JUnit 版本(或测试框架)如何。

    基于注释

    使用@Mock-注解和对MockitoAnnotations::initMocks的相应调用 到create mocks 的工作原理与 JUnit 版本无关(或测试框架,但 Java 9 可能会在此处干扰,具体取决于测试代码是否最终在模块中)。

    Mockito 扩展

    JUnit 5 有 a powerful extension model 和 Mockito 最近在组/工件 ID org.mockito : mockito-junit-jupiter 下发布了一个。

    您可以通过将@ExtendWith(MockitoExtension.class) 添加到测试类并使用@Mock 注释模拟字段来应用扩展。来自MockitoExtension的JavaDoc:

    @ExtendWith(MockitoExtension.class)
    public class ExampleTest {
    
        @Mock
        private List list;
    
        @Test
        public void shouldDoSomething() {
            list.add(100);
        }
    
    }
    

    The MockitoExtension documentation 描述了实例化 mock 的其他方法,例如使用构造函数注入(如果您在测试类中引用 final 字段)。

    没有规则,没有跑步者

    JUnit 4 规则和运行器在 JUnit 5 中不起作用,因此无法使用 MockitoRuleMockito runner

    【讨论】:

    • 现在有一个官方的 Mockito Junit5 扩展,相当于 MockitoJUnitRunner -> mockito-junit-jupiter
    • Mockito 官方扩展发布时,写了一篇博文,详细介绍了如何配置和使用它:solidsoft.wordpress.com/2018/03/27/…
    • 注解@Test的方法是否需要公开或者“包私有”是否足够好?
    • 使用 Jupiter(通常称为“JUnit 5”)运行测试时,测试方法只需要包可见。
    • 回到这一点 - 有没有首选的方法?有什么建议吗?还是基于意见?
    【解决方案2】:

    使用 Mockito 的 MockitoExtension。扩展包含在一个新的工件mockito-junit-jupiter

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>2.23.4</version>
        <scope>test</scope>
    </dependency>
    

    它允许您像使用 JUnit 4 一样编写测试:

    import org.mockito.junit.jupiter.MockitoExtension;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    
    @ExtendWith(MockitoExtension.class)
    class MyTest {
    
        @Mock
        private Foo foo;
    
        @InjectMocks
        private Bar bar; // constructor injection
    
        ...
    }
    

    【讨论】:

    • @ExtendWith(MockitoExtension.class) 相当于 JUnit4 的 @RunWith(MockitoJUnitRunner.class)
    • 我可以使用 JUnit5 中的 MockitoExtension.class 对 Mock 对象的方法执行具有不同返回值的方法的多次调用
    • @RajHassani 是的,您可以,请参阅here
    【解决方案3】:

    有不同的方法可以做,但更清洁的方法也尊重 JUnit 5 的理念是为 Mockito 创建一个org.junit.jupiter.api.extension.Extension

    1) Creating mocks manually 失去了额外的 Mockito 检查的好处,以确保您正确使用框架。

    2) 在每个测试类中调用 MockitoAnnotations.initMocks(this) 是我们可以避免的样板代码。
    在抽象类中进行此设置也不是一个好的解决方案。
    它将每个测试类耦合到一个基类。
    如果你有充分的理由需要一个新的基础测试类,你可以使用一个 3 级的类层次结构。请避免这种情况。

    3) 测试规则是 JUnit 4 的特殊性。
    想都别想。
    documentation 很清楚这一点:

    但是,如果您打算为 JUnit 5 开发新的扩展,请 使用 JUnit Jupiter 的新扩展模型,而不是基于规则的 JUnit 4 的模型。

    4) Test Runner 确实不是扩展 JUnit 5 框架的方法。
    由于 JUnit 5 Extensions,JUnit 5 提供了一个用于编写测试的扩展模型,从而简化了 JUnit 4 的 Runners。
    想都别想。

    所以支持org.junit.jupiter.api.extension.Extension 方式。


    编辑:实际上,Mockito 捆绑了一个木星扩展:mockito-junit-jupiter

    那么,使用起来非常简单:

    import org.mockito.junit.jupiter.MockitoExtension;
    
    @ExtendWith(MockitoExtension.class)
    public class FooTest {
         ...    
    }
    

    这是对乔纳森出色回答的补充。

    通过添加 mockito-junit-jupiter 工件作为依赖项,使用 @ExtendWith(MockitoExtension.class) 在执行测试时会产生以下异常:

    java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation(Ljava/util/Optional;Ljava/lang/Class;)Ljava/util/Optional;

    问题是mockito-junit-jupiter 依赖于两个独立的库。 例如mockito-junit-jupiter:2.19.0

    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <version>2.19.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.1.0</version>
      <scope>runtime</scope>
    </dependency>
    

    问题是我使用了junit-jupiter-api:5.0.1

    因此,junit-jupiter-api 在 API 方面仍然经常移动,请确保您依赖于 mockito-junit-jupiter 所依赖的同一版本的 junit-jupiter-api

    【讨论】:

    • 为什么mockito-junit-jupiter 不提取正确版本的junit-jupiter-api
    • @haelix 因为用于此依赖项的版本策略依赖于 Mockito 库。看看这里的版本mockito-junit-jupiter:2.19.0。而 JUnit Jupiter 版本以 5 开头。 mockito-junit-jupiter 应该在其工件标识符中指定两件事(Mockito 版本和 JUnit Jupiter 版本)以使事情更清晰。例如mockito-junit-jupiter-5.1:2.19.0 表示该库是为 JUnit Jupiter 5.1 设计的。
    • MockitoExtensionmockito-core 版本 3.0.0 中似乎不存在。
    • @Thunderforge 这在mockito-junit-jupiter中定义
    【解决方案4】:

    你必须使用新的@ExtendWith注解。

    很遗憾,还没有发布任何扩展。 在github 上,您可以看到扩展的测试版实现。以demo test为例。

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多