Cambio de clase JUnit o comportamiento método de pruebas de integración

matfur92:

Tengo una aplicación java (sin el interior de primavera) que quiero prueba con una prueba de integración.

Mi caso de uso principal es la función principal que con una entrada especificada hacer algunas cosas en la base de datos y enviar alguna petición a dos servicios diferentes, uno de SOAP y REST uno.

Ahora tengo una configuración de trabajo JUnit (dividido en las pruebas de unidad y de integración) + io.fabric8: estibador-maven-plugin que utilizar una imagen de ventana acoplable para la base de datos durante las pruebas de integración.

Lo que estoy tratando de hacer es añadir una maqueta para estos 2 servicios, en particular, el método que se utiliza para llamar directamente al servicio externo.

El gran problema es que tengo esta estructura:

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

donde tengo:

class NotifierHandler{
    String sendNotification(Json j){
        ...
        [call to REST service with some parameters]
        ...
        ...
        [call to SOAP service with some parameters]
        ...
    }
}

Lo que necesito : Llamada de A.mainFunction(r)tener, en el entorno de prueba, sustituyó al NotifierHandler con un FakeNotifierHandler y / o cambiar el comportamiento del método sendNotification().

Problemas reales : El uso de Mockito y PowerMock ahora tienen el problema de que no soy capaz de cambiar a nivel mundial y directamente la NotifierHandler clase con FakeNotifierHandler. Lo mismo tratando de cambiar el comportamiento del método.

En particular, lo que necesito es crear una

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]
        ...
    }
}

Leyendo todo ejemplo que tryed vi sólo ejemplos simples que cambian el valor de retorno de un método y no el comportamiento de un método de una clase utilizada por el otro, y otro que estoy usando como punto de inicio de la prueba de integración.

NOTA: Probablemente hay una forma rápida de hacer esto, pero yo soy muy nuevo en este tipo de pruebas (Mockito, PowerMock, ...) y he encontrado ningún ejemplo de este extraño caso en particular.

EDIT: no es similar a cómo burlarse constructor PowerMockito porque necesito cambiar el comportamiento del método, no sólo el valor de retorno.

Muchas gracias por adelantado

matfur92:

He encontrado una solución que funciona muy bien y es muy simple!

La solución es PowerMock ( https://github.com/powermock/powermock ) y, en particular, en lugar de la creación de una instancia de una clase con otra: https://github.com/powermock/powermock/wiki/mockito#how- a-maqueta-construcción de nuevos objetos

Sólo hay un problema en mi proyecto y es JUnit 5. PowerMock JUnit 4 de soporte y por esta razón, sólo para algunas pruebas de la solución se utiliza. Con el fin de hacer esto existe la necesaria para reemplazar

import org.junit.jupiter.api.Test;

con

import org.junit.Test;

Para utilizar teh " whenNew () métodos" que había Extented la clase que en las pruebas debe ser reemplazado y tengo sobrescribe únicos métodos que son necesarios para la prueba de integración. La gran ventaja de esta solución es que mi código es virgen y que se puede utilizar este enfoque también con el código antiguo y sin el riesgo de introducir regresiones durante el refactor del código.

En cuanto al código de una prueba de integración, aquí un ejemplo:

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

Aquí, la configuración de la 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>

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=313198&siteId=1
Recomendado
Clasificación