Cómo burlarse de una clase final con mockito

Resuelto buttowski asked hace 11 años • 29 respuestas

Tengo una clase final, algo como esto:

public final class RainOnTrees{

   public void startRain(){

        // some code here
   }
}

Estoy usando esta clase en alguna otra clase como esta:

public class Seasons{

   RainOnTrees rain = new RainOnTrees();

   public void findSeasonAndRain(){

        rain.startRain();

    }
}

y en mi clase de prueba JUnit porque Seasons.javaquiero burlarme de la RainOnTreesclase. ¿Cómo puedo hacer esto con Mockito?

buttowski avatar Jan 12 '13 18:01 buttowski
Aceptado

Burlarse de clases/métodos finales/estáticos es posible solo con Mockito v2.

agregue esto en su archivo gradle:

testImplementation 'org.mockito:mockito-inline:2.13.0'

Esto no es posible con Mockito v1, de las preguntas frecuentes de Mockito :

¿Cuáles son las limitaciones de Mockito?

  • Necesita java 1.5+

  • No puedo burlarme de las clases finales.

...

 avatar Jan 12 '2013 11:01

¡Mockito 2 ahora admite clases y métodos finales!

Pero por ahora se trata de una característica en "incubación". Requiere algunos pasos para activarlo que se describen en Novedades de Mockito 2 :

La burla de las clases y métodos finales es una característica opcional en incubación . Utiliza una combinación de instrumentación del agente Java y subclases para permitir la burla de estos tipos. Como esto funciona de manera diferente a nuestro mecanismo actual y este tiene diferentes limitaciones y como queremos recopilar experiencia y comentarios de los usuarios, esta función tuvo que activarse explícitamente para que esté disponible; se puede hacer a través del mecanismo de extensión Mockito creando el archivo src/test/resources/mockito-extensions/org.mockito.plugins.MockMakerque contiene una sola línea:

mock-maker-inline

Después de crear este archivo, Mockito usará automáticamente este nuevo motor y se puede hacer:

 final class FinalClass {
   final String finalMethod() { return "something"; }
 }

 FinalClass concrete = new FinalClass(); 

 FinalClass mock = mock(FinalClass.class);
 given(mock.finalMethod()).willReturn("not anymore");

 assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());

En hitos posteriores, el equipo aportará una forma programática de utilizar esta función. Identificaremos y brindaremos soporte para todos los escenarios imposibles de burlar. ¡Estén atentos y díganos qué piensa de esta función!

WindRider avatar Oct 13 '2016 10:10 WindRider

agregue esto en su archivo de compilación:

  • si usa gradle :build.gradle
testImplementation 'org.mockito:mockito-inline:2.13.0'
  • si usa maven :pom.xml
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>2.13.0</version>
    <scope>test</scope>
</dependency>

esta es una configuración para hacer que Mockito funcione con las clases finales.

Si se enfrentó a la dependencia Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.) Agregar el Byte Buddy a su build.gradlearchivo:

testImplementation 'net.bytebuddy:byte-buddy-agent:1.10.19'

src: https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy

BennyP avatar Feb 22 '2018 08:02 BennyP

No puedes burlarte de una clase final con Mockito, ya que no puedes hacerlo tú solo.

Lo que hago es crear una clase no final para envolver la clase final y usarla como delegado. Un ejemplo de esto es TwitterFactoryla clase, y esta es mi clase simulada:

public class TwitterFactory {

    private final twitter4j.TwitterFactory factory;

    public TwitterFactory() {
        factory = new twitter4j.TwitterFactory();
    }

    public Twitter getInstance(User user) {
        return factory.getInstance(accessToken(user));
    }

    private AccessToken accessToken(User user) {
        return new AccessToken(user.getAccessToken(), user.getAccessTokenSecret());
    }

    public Twitter getInstance() {
        return factory.getInstance();
    }
}

La desventaja es que hay mucho código repetitivo; la ventaja es que puede agregar algunos métodos que puedan estar relacionados con el negocio de su aplicación (como getInstance, que toma un usuario en lugar de un accessToken, en el caso anterior).

En su caso, crearía una RainOnTreesclase no final que delegaría a la clase final. O, si puede hacerlo no definitivo, sería mejor.

Luigi avatar Jan 12 '2013 11:01 Luigi

En Mockito 3 y más tengo el mismo problema y lo solucioné desde este enlace

Simule clases y métodos finales con Mockito de la siguiente manera

Antes de que Mockito pueda usarse para burlarse de clases y métodos finales, debe configurarse.

Necesitamos agregar un archivo de texto al directorio src/test/resources/mockito-extensions del proyecto llamado org.mockito.plugins.MockMaker y agregar una sola línea de texto:

mock-maker-inline

Mockito comprueba el directorio de extensiones en busca de archivos de configuración cuando está cargado. Este archivo permite burlarse de los métodos y clases finales.

Sattar avatar Dec 28 '2019 15:12 Sattar