为了账号安全,请及时绑定邮箱和手机立即绑定

JUnit 更改集成测试中的类或方法行为

JUnit 更改集成测试中的类或方法行为

慕沐林林 2023-11-01 16:59:13
我有一个java应用程序(里面没有Spring),我想用集成测试来测试它。我的主要用例是主要功能,它使用指定的输入在数据库上执行一些操作并向两个不同的服务(一个 SOAP 和一个 REST)发送一些请求。现在我有一个有效的 JUnit 配置(分为单元测试和集成测试)+ io.fabric8:docker-maven-plugin,它在集成测试期间使用 docker 映像作为数据库。我想做的是为这两个服务添加模拟,特别是用于直接调用外部服务的方法。最大的问题是我有这样的结构:class A{    Result mainFunction(Request r){        ....        B b = new B(params);        b.logEvent(someParameters)        ....    }}class B{    int logEvent(Object someParameters){        ....        NotifierHandler nh = new NotifierHandler(param1);        nh.sendNotification(json);        ....    }}我在哪里:class NotifierHandler{    String sendNotification(Json j){        ...        [call to REST service with some parameters]        ...        ...        [call to SOAP service with some parameters]        ...    }}我需要什么:A.mainFunction(r)在测试环境中调用,用 FakeNotifierHandler 替换 NotifierHandler 和/或更改方法的行为sendNotification()。实际问题:现在使用 Mockito 和 PowerMock 时遇到的问题是,我无法使用 FakeNotifierHandler 全局直接更改类 NotifierHandler。同样尝试改变该方法的行为。特别是,我需要的是创建一个class FakeNotifierHandler{    String sendNotification(Json j){        ...        [save on an HashMap what I should send to the REST service]        ...        ...        [save on another HashMap what I should send to the SOAP service]        ...    }}阅读我尝试过的所有示例,我只看到了更改方法返回值的简单示例,而不是更改一个类的一个方法的行为,该方法被另一个类和另一个我用作集成测试起点的类所使用。注意:可能有一种快速的方法可以做到这一点,但我对这种类型的测试(Mockito,PowerMock,...)非常陌生,并且我没有找到这种特殊奇怪情况的示例。
查看完整描述

1 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

我找到了一个非常有效的解决方案,而且非常简单!

解决方案是 PowerMock(https://github.com/powermock/powermock),特别是用另一个类实例替换类实例的创建: https: //github.com/powermock/powermock/wiki/mockito#how-模拟新对象的构造

我的项目中只有一个问题,那就是 JUnit 5。PowerMock 支持 JUnit 4,因此,仅在解决方案的某些测试中使用它。为了做到这一点,需要更换

import org.junit.jupiter.api.Test;

import org.junit.Test;

为了使用“ whenNew() ”方法,我扩展了测试中必须替换的类,并且仅覆盖了集成测试所需的方法。此解决方案的最大好处是我的代码未受影响,并且我也可以在旧代码上使用此方法,而无需在代码重构期间引入回归的风险。

关于集成测试的代码,这里有一个例子:

import org.junit.jupiter.api.DisplayName;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.powermock.api.mockito.PowerMockito;

import org.powermock.core.classloader.annotations.PowerMockIgnore;

import org.powermock.core.classloader.annotations.PrepareForTest;

import org.powermock.modules.junit4.PowerMockRunner;


@RunWith(PowerMockRunner.class)

@PowerMockIgnore({"javax.crypto.*" }) // https://github.com/powermock/powermock/issues/294

@PrepareForTest(LegacyCoreNetworkClassPlg.class) // it is the class that contains the "new SOAPCallHelper(..)" code that I want to intercept and replace with a stub

public class ITestExample extends InitTestSuite {

    @Test

    @DisplayName("Test the update of a document status")

    public void iTestStubLegacyNetworkCall() throws Exception {


        // I'm using JUnit 4

        // I need to call @BeforeAll defined in InitTestSuite.init();

        // that works only with JUnit 5

        init();


        LOG.debug("IN stubbing...");

        SOAPCallHelperStub stub = new SOAPCallHelperStub("empty");

        PowerMockito.whenNew(SOAPCallHelper.class).withAnyArguments().thenReturn(stub);

        LOG.debug("OUT stubbing!!!");


        LOG.debug("IN iTestStubLegacyNetworkCall");

        ...

        // Here I can create any instance of every class, but when an instance of 

        // LegacyCoreNetworkClassPlg.class is created directly or indirectly, PowerMock

        // is checking it and when LegacyCoreNetworkClassPlg.class will create a new

        // instance of SOAPCallHelper it will change it with the 

        // SOAPCallHelperStub instance.

        ...

        LOG.debug("OUT iTestStubLegacyNetworkCall");

    }

}

这里是pom.xml的配置


    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <junit.jupiter.version>5.5.2</junit.jupiter.version>

    <junit.vintage.version>5.5.2</junit.vintage.version>

    <junit.platform.version>1.3.2</junit.platform.version>

    <junit.platform.engine.version>1.5.2</junit.platform.engine.version>

    <powermock.version>2.0.2</powermock.version>


    <!-- FOR TEST -->

    <dependency>

        <groupId>org.junit.jupiter</groupId>

        <artifactId>junit-jupiter-api</artifactId>

        <version>${junit.jupiter.version}</version>

        <scope>test</scope>

    </dependency>

    <dependency>

        <groupId>junit</groupId>

        <artifactId>junit</artifactId>

        <scope>test</scope>

    </dependency>

    <!-- Only required to run tests in an IDE that bundles an older version -->

    <dependency>

        <groupId>org.junit.platform</groupId>

        <artifactId>junit-platform-launcher</artifactId>

        <version>${junit.platform.version}</version>

        <scope>test</scope>

    </dependency>

    <!-- Only required to run tests in an IDE that bundles an older version -->

    <dependency>

        <groupId>org.junit.jupiter</groupId>

        <artifactId>junit-jupiter-engine</artifactId>

        <version>${junit.jupiter.version}</version>

        <scope>test</scope>

    </dependency>

    <!-- Only required to run tests in an IDE that bundles an older version -->

    <dependency>

        <groupId>org.junit.vintage</groupId>

        <artifactId>junit-vintage-engine</artifactId>

        <version>${junit.vintage.version}</version>

        <scope>test</scope>

    </dependency>

    <dependency>

        <groupId>org.junit.platform</groupId>

        <artifactId>junit-platform-engine</artifactId>

        <version>${junit.platform.engine.version}</version>

        <scope>test</scope>

    </dependency>

    <dependency>

        <groupId>org.junit.jupiter</groupId>

        <artifactId>junit-jupiter-params</artifactId>

        <version>${junit.vintage.version}</version>

        <scope>test</scope>

    </dependency>


    <dependency>

        <groupId>org.powermock</groupId>

        <artifactId>powermock-module-junit4</artifactId>

        <version>${powermock.version}</version>

        <scope>test</scope>

    </dependency>

    <dependency>

        <groupId>org.powermock</groupId>

        <artifactId>powermock-api-mockito2</artifactId>

        <version>${powermock.version}</version>

        <scope>test</scope>

    </dependency>


查看完整回答
反对 回复 2023-11-01
  • 1 回答
  • 0 关注
  • 65 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信