0

0

JUnit 参数化测试中 Mock 对象返回参数化值的正确方法

花韻仙語

花韻仙語

发布时间:2025-07-08 18:04:12

|

278人浏览过

|

来源于php中文网

原创

junit 参数化测试中 mock 对象返回参数化值的正确方法

本文介绍了在使用 JUnit 参数化测试和 Mockito 框架时,如何正确地配置和使用 Mock 对象,使其能够根据参数化测试的输入参数返回不同的值。重点在于 runner 的选择,通过使用 MockitoExtension 解决了 InvalidUseOfMatchersException 异常,并提供了一个可运行的示例代码。

在使用 JUnit 进行单元测试时,参数化测试可以方便地使用不同的输入数据运行相同的测试逻辑。结合 Mockito 框架,我们可以模拟外部依赖的行为,从而更好地隔离被测代码。然而,在参数化测试中,如果 Mock 对象的行为依赖于参数化测试的输入,可能会遇到一些问题。本文将介绍如何正确地配置和使用 Mock 对象,使其能够根据参数化测试的输入参数返回不同的值。

问题分析

在使用 Mockito 时,常见的错误之一是 InvalidUseOfMatchersException,这通常发生在参数匹配器(如 any())被错误地使用时。例如,在没有进行 stubbing 或 verification 的情况下使用了参数匹配器。

解决方案

解决此问题的关键在于正确地配置 JUnit 运行器和 Mockito 扩展。以下是推荐的步骤:

  1. 使用 MockitoExtension

    确保你的测试类使用了 MockitoExtension 作为 JUnit 的扩展。这可以通过在类上添加 @ExtendWith(MockitoExtension.class) 注解来实现。MockitoExtension 负责初始化 Mockito 的 Mock 对象,并处理相关的生命周期。

    @ExtendWith(MockitoExtension.class)
    public class FooTest {
    
        @Mock
        MockedObject mockedObject;
    
        @InjectMocks
        Foo underTest;
    
        // ...
    }

    注意:这里使用了 @Mock 注解,它与 @Mocked 注解功能类似,都是用来创建 Mock 对象的。但 @Mock 是 Mockito 提供的标准注解,建议使用它。

  2. 参数化测试数据提供

    使用 @MethodSource 注解指定一个提供参数化测试数据的静态方法。该方法返回一个 Stream,其中每个 Arguments 对象包含测试方法的输入参数。

    Img.Upscaler
    Img.Upscaler

    免费的AI图片放大工具

    下载
    @ParameterizedTest
    @MethodSource("dataProvider")
    public void test_ParametrizedTest(MockedInput mockedInput, Output expectedReturn) {
    
        // Given
        when(mockedObject.method(mockedInput))
            .thenReturn(expectedReturn);
    
        // when
        val result = underTest.method();
    
        // then
        assertEquals(expectedReturn.getCode(), result.getCode());
    
    }
    
    private static Stream dataProvider() {
        MockedInput mockedInput1 = new MockedInput("S1");
        MockedInput mockedInput2 = new MockedInput("S2");
        return Stream.of(
            Arguments.of(mockedInput1, Output.builder().code(CodeEnum.S1).build()),
            Arguments.of(mockedInput2, Output.builder().code(CodeEnum.S2).build())
        );
    }

    在这个例子中,dataProvider 方法返回一个包含 MockedInput 和 Output 对象的 Stream。每个 Arguments 对象都对应一个测试用例。

  3. Mock 对象的 Stubbing

    在测试方法中,使用 when(mockedObject.method(mockedInput)).thenReturn(expectedReturn) 来指定 Mock 对象的行为。这里,mockedInput 是参数化测试的输入参数,expectedReturn 是期望的返回值。Mockito 会根据传入的 mockedInput 参数,返回相应的 expectedReturn 值。

  4. 断言

    最后,使用 assertEquals 或其他断言方法来验证被测代码的行为是否符合预期。

完整示例

以下是一个完整的示例代码,展示了如何在 JUnit 参数化测试中使用 Mockito 模拟对象,并根据不同的输入参数返回不同的值:

import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;

import lombok.Builder;
import lombok.Data;
import lombok.Value;

import java.util.stream.Stream;

@ExtendWith(MockitoExtension.class)
public class FooTest {

    @Mock
    MockedObject mockedObject;

    @InjectMocks
    Foo underTest;

    @ParameterizedTest
    @MethodSource("dataProvider")
    public void test_ParametrizedTest(MockedInput mockedInput, Output expectedReturn) {

        // Given
        when(mockedObject.method(mockedInput))
            .thenReturn(expectedReturn);

        // when
        Output result = underTest.method(mockedInput);

        // then
        assertEquals(expectedReturn.getCode(), result.getCode());

    }

    private static Stream dataProvider() {
        MockedInput mockedInput1 = new MockedInput("S1");
        MockedInput mockedInput2 = new MockedInput("S2");
        return Stream.of(
            Arguments.of(mockedInput1, Output.builder().code(CodeEnum.S1).build()),
            Arguments.of(mockedInput2, Output.builder().code(CodeEnum.S2).build())
        );
    }

    // 辅助类
    public static enum CodeEnum {
        S1("S1"),
        S2("S2");

        private String value;

        CodeEnum(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }
    }

    @Value
    public static class MockedInput {
        String input;
    }

    @Builder
    @Data
    public static class Output {
        CodeEnum code;
    }

    public static class Foo {
        private MockedObject mockedObject;

        public Foo(MockedObject mockedObject) {
            this.mockedObject = mockedObject;
        }

        public Output method(MockedInput input) {
            return mockedObject.method(input);
        }
    }

    public static class MockedObject {
        public Output method(MockedInput input) {
            // This method will be mocked
            return null;
        }
    }
}

注意事项

  • 确保你的 JUnit 和 Mockito 版本兼容。
  • 避免在参数化测试中使用过于复杂的参数匹配器,尽量使用具体的参数值进行 Mock 对象的 stubbing。
  • 如果遇到 InvalidUseOfMatchersException,首先检查是否正确地使用了 MockitoExtension,并确保参数匹配器只在 stubbing 或 verification 中使用。

总结

通过使用 MockitoExtension 和 @MethodSource 注解,我们可以轻松地在 JUnit 参数化测试中使用 Mockito 模拟对象,并根据不同的输入参数返回不同的值。这种方法可以有效地隔离被测代码,并提高单元测试的质量。

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
软件测试常用工具
软件测试常用工具

软件测试常用工具有Selenium、JUnit、Appium、JMeter、LoadRunner、Postman、TestNG、LoadUI、SoapUI、Cucumber和Robot Framework等等。测试人员可以根据具体的测试需求和技术栈选择适合的工具,提高测试效率和准确性 。

423

2023.10.13

java测试工具有哪些
java测试工具有哪些

java测试工具有JUnit、TestNG、Mockito、Selenium、Apache JMeter和Cucumber。php还给大家带来了java有关的教程,欢迎大家前来学习阅读,希望对大家能有所帮助。

293

2023.10.23

Java 单元测试
Java 单元测试

本专题聚焦 Java 在软件测试与持续集成流程中的实战应用,系统讲解 JUnit 单元测试框架、Mock 数据、集成测试、代码覆盖率分析、Maven 测试配置、CI/CD 流水线搭建(Jenkins、GitHub Actions)等关键内容。通过实战案例(如企业级项目自动化测试、持续交付流程搭建),帮助学习者掌握 Java 项目质量保障与自动化交付的完整体系。

19

2025.10.24

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

454

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

6

2025.12.06

苹果官网入口直接访问
苹果官网入口直接访问

苹果官网直接访问入口是https://www.apple.com/cn/,该页面具备0.8秒首屏渲染、HTTP/3与Brotli加速、WebP+AVIF双格式图片、免登录浏览全参数等特性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

115

2025.12.24

拼豆图纸在线生成器
拼豆图纸在线生成器

拼豆图纸生成器有PixelBeads在线版、BeadGen和“豆图快转”;推荐通过pixelbeads.online或搜索“beadgen free online”直达官网,避开需注册的诱导页面。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

84

2025.12.24

俄罗斯搜索引擎yandex官方入口地址(最新版)
俄罗斯搜索引擎yandex官方入口地址(最新版)

Yandex官方入口网址是https://yandex.com。用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

553

2025.12.24

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

155

2025.12.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号