@Autowired no debe trabajar sin @RunWith(SpringRunner.class) pero sí

Aquí hay una clase de pruebas de unidad para una capa de repositorio de datos de primavera de java. Tengo una capa de repositorio de datos de primavera en la que la anotación @Autowired se utiliza para inyectar TestEntityManager tipo objeto (pertenece al paquete de datos de primavera). El autowiring funciona silbido añadiendo @RunWith(SpringRunner.class) anotación ! ¿Cuál es el problema? Bueno, creo que la inyección no debe ser posible silbido añadiendo @RunWith(SpringRunner.class) a la clase: no debe funcionar sin ella teóricamente. ¿Cómo es posible? ¿Alguien tiene alguna respuesta?

, titulado ver el código completo de aplicación de arranque de primavera en github disponible aquí

  • Alguien más ha tenido el problema opuesto en apiloverflow :

Alguien más ha tenido el problema opuesto: ver enlace aquí

Aquí está mi extraño bloque de código que increíblemente funciona :

paquete org.loiz.demo;

import org.assertj.core.api.BDDAssertions;
import org.junit.Assert;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test ;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Order ;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import demo.LoizBootSpringDemoApplication;
import demo.crepository.UserRepositoryInterface;
import demo.dmodel.User;
import demo.helper.helperUtils;

//Test de la couche de persistence
//@RunWith(SpringRunner.class)
@DataJpaTest
@ContextConfiguration(classes = { LoizBootSpringDemoApplication.class})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@SuppressWarnings("unused")
public class LoizPersistenceTest 
{
    
    @Autowired
    private TestEntityManager testEntityManager;

    @Autowired
    private UserRepositoryInterface repository; 

    private static Long idStub ;
    
    @Test
    @Order(1)
    @Rollback(false)
    @DisplayName("Test de sauvegarde d\'un user \"prenom21 Nom21\"")    
    public void saveShouldMapCorrectly() throws Exception {
        
        User userStub = new User("prenom21", "Nom21");                       
        
        User UserSaved = this.testEntityManager.persistFlushFind(userStub);
        
        BDDAssertions.then(UserSaved.getId()).isNotNull();                    
        idStub = UserSaved.getId() ;
        
        User UserRead = this.testEntityManager.find(User.class, idStub) ;       
        
        BDDAssertions.then(UserSaved.getFirstName()).isNotBlank();
        BDDAssertions.then(UserSaved.getFirstName()).isEqualToIgnoringCase("prenom21");
        

        BDDAssertions.then(UserSaved.getLastName()).isEqualToIgnoringCase("Nom21");
        BDDAssertions.then(UserSaved.getLastName()).isNotBlank();
    }

    @Test
    @Order(2) 
    @DisplayName("Test d'existence du user \"prenom21 Nom21\"") 
    public void readShouldMapCorrectly() throws Exception {
        User userStub = new User(idStub, "prenom21", "Nom21");          
        User userFetched  = this.testEntityManager.find(User.class, idStub) ;
        
        String sUserStub = userStub.toString() ;        
        String sUserFetched = userFetched.toString() ;      
        
        
        boolean bolSameObject = userStub.equals(userFetched) ;
        
        boolean bolAttrEgalEgal = sUserStub == sUserFetched ;       
        
        boolean bolStringEqual = sUserStub.equals(sUserFetched) ;           
        
        boolean bBeanUtil = helperUtils.haveSamePropertyValues (User.class,userStub,userFetched) ;
        
                
        Assert.assertTrue(bBeanUtil);
        
    }

}

Tal vez sea normal, pero ¿qué tengo que saber? Le agradecería una respuesta, por favor:)

, titulado ver el código completo de aplicación de arranque de primavera en github disponible aquí

Pregunta hecha hace 3 años, 4 meses, 29 días - Por devdynamo


4 Respuestas:

  • @RunWith(SpringRunner.class) se utiliza para la prueba de junit 4. Pero en nuestro caso, es Junit 5 que se utiliza. Eso es lo que podemos ver leyendo pom.xml archivo (utilización de junit.jupiter el artefacto prueba eso). Así que... @RunWith(SpringRunner.class) no tiene efectos para manejar contenedor de muelles. debe ser reemplazado por @ExtendWith(SpringExtension.class).

    Siempre:

    @DataJpaTest ya "contiene" @ExtendWith(SpringExtension.class) !!! Así que no necesitamos añadir @ExtendWith(SpringExtension.class) cuando @DataJpaTest se utiliza. @DataJpaTest permitirá probar la capa de repositorio de datos de primavera, pero también garantizará la inyección de dependencia de primavera. Es decir, y agitando, puedes usar @Autowired anotación para una clase anotada @DataJpaTest (una capa de repositorio de datos de primavera).

    Respondida el Dec 17, 2020 a las 20:54 - por binarybard1cc8

    Votos positivos: 0 | Votos negativos: 0

  • De las importaciones junit.jupiter Veo que estás usando junit-5, estaban @RunWith pertenece a junit-4, y para referencia @ExtendWith no es mandataroy para la prueba de junit-5 y si desea utilizar un corredor específico que todavía requiere @ExtendsWith pero @DataJpaTest en sí mismo está anotado @ExtendsWith no necesitas hacer esto explícitamente

    En JUnit 5, el @RunWith la anotación ha sido reemplazada por el más poderoso @ExtendWith anotación.

    Para usar esta clase, simplemente anota una clase de prueba basada en JUnit 4 con @RunWith(SpringJUnit4ClassRunner.class) o @RunWith(SpringRunner.class).

    Respondida el Dec 17, 2020 a las 21:02 - por binarybard1cc8

    Votos positivos: 0 | Votos negativos: 0

  • El problema que mencionas acerca de que la inyección de dependencias con @Autowired no debería funcionar sin @RunWith(SpringRunner.class) es una confusión común que puede surgir al principio al trabajar con pruebas unitarias en Spring.

    La anotación @RunWith(SpringRunner.class) se utilizaba en versiones anteriores de JUnit para habilitar la funcionalidad de ejecutar pruebas de Spring en el entorno de Spring. Sin embargo, a partir de JUnit 5, se recomienda utilizar las anotaciones proporcionadas por el propio framework de Spring, como @DataJpaTest, @WebMvcTest, etc., en lugar de @RunWith.

    En tu código, estás utilizando JUnit 5 con la anotación @RunWith(SpringRunner.class), lo cual no es necesario. La anotación que deberías utilizar para indicar que estas pruebas son de persistencia de datos en Spring es @DataJpaTest, que ya estás utilizando.

    Por lo tanto, el autowiring con @Autowired funciona correctamente en tu clase de prueba porque estás utilizando la anotación @DataJpaTest, que se encarga de configurar el contexto de Spring para las pruebas de persistencia de datos.

    En resumen, puedes eliminar la anotación @RunWith(SpringRunner.class) de tu clase de pruebas y tu código seguirá funcionando de la misma manera. La anotación @DataJpaTest es la que se encarga de configurar el contexto de Spring para las pruebas de persistencia de datos en este caso.

    Espero que esta explicación aclare tus dudas. ¡Si tienes alguna pregunta adicional, no dudes en decírmelo!

    Respondida el Dec 18, 2020 a las 20:50 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Problema:

    La anotación @Autowired está inyectando correctamente un objeto de tipo TestEntityManager incluso sin la anotación @RunWith(SpringRunner.class).

    Explicación:

    Normalmente, la anotación @RunWith(SpringRunner.class) es necesaria para que la anotación @Autowired funcione en las pruebas de Spring. Sin embargo, en tu caso, parece que la anotación @DataJpaTest está proporcionando el entorno necesario para la inyección automática sin necesidad de @RunWith(SpringRunner.class).

    La anotación @DataJpaTest es una anotación compuesta que incluye la anotación @ExtendWith(SpringExtension.class) internamente. Por lo tanto, cuando se utiliza @DataJpaTest, la anotación @ExtendWith(SpringExtension.class) se añade implícitamente a la clase de prueba.

    La anotación @ExtendWith(SpringExtension.class) es responsable de cargar el contexto de Spring y habilitar el autowire. Por lo tanto, aunque no hayas utilizado @RunWith(SpringRunner.class), la anotación @DataJpaTest está proporcionando el mecanismo necesario para que @Autowired funcione.

    Respuesta a la pregunta:

    La inyección automática está funcionando en este caso debido al uso de la anotación @DataJpaTest, que proporciona el entorno necesario para el autowire, incluso sin @RunWith(SpringRunner.class). Esto es una desviación del comportamiento estándar, pero es una característica intencionada de la anotación @DataJpaTest.

    Respondida el Dec 18, 2020 a las 20:56 - por Gemini

    Votos positivos: 0 | Votos negativos: 0