No se puede encontrar una @SpringBootConfiguration al hacer un JpaTest

186

Soy nuevo en frameworks (acabo de pasar la clase) y esta es la primera vez que uso Spring Boot.

Estoy tratando de ejecutar una prueba simple de Junit para ver si mis CrudRepositories realmente funcionan.

El error que sigo recibiendo es:

Incapaz de encontrar una @SpringBootConfiguration, debe usar @ContextConfiguration o @SpringBootTest (classes = ...) con su prueba java.lang.IllegalStateException

¿Spring Boot no se configura a sí mismo?

Mi clase de prueba:

@RunWith(SpringRunner.class)
@DataJpaTest
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class JpaTest {

@Autowired
private AccountRepository repository;

@After
public void clearDb(){
    repository.deleteAll();
}

 @Test
 public void createAccount(){
     long id = 12;
     Account u = new Account(id,"Tim Viz");
     repository.save(u);

     assertEquals(repository.findOne(id),u);

 }


 @Test
 public void findAccountByUsername(){
     long id = 12;
     String username = "Tim Viz";
     Account u = new Account(id,username);
     repository.save(u);

     assertEquals(repository.findByUsername(username),u);

 }

Mi iniciador de aplicaciones Spring Boot:

@SpringBootApplication
@EnableJpaRepositories(basePackages = {"domain.repositories"})
@ComponentScan(basePackages = {"controllers","domain"})
@EnableWebMvc
@PropertySources(value    {@PropertySource("classpath:application.properties")})
    @EntityScan(basePackages={"domain"})
    public class Application extends SpringBootServletInitializer {
        public static void main(String[] args) {
            ApplicationContext ctx = SpringApplication.run(Application.class, args);         

        }
    }

Mi repositorio:

public interface AccountRepository extends CrudRepository<Account,Long> {

    public Account findByUsername(String username);

    }
}
Thomas Billet
fuente

Respuestas:

264

De hecho, Spring Boot se configura en su mayor parte. Probablemente ya pueda deshacerse de gran parte del código que publicó, especialmente en Application.

Desearía que hubieras incluido los nombres de los paquetes de todas tus clases, o al menos los de Applicationy JpaTest. La cuestión @DataJpaTesty algunas otras anotaciones es que buscan una @SpringBootConfigurationanotación en el paquete actual y, si no pueden encontrarla allí, atraviesan la jerarquía del paquete hasta que la encuentran.

Por ejemplo, si el nombre completo para su clase de prueba fue com.example.test.JpaTesty el de su solicitud fue com.example.Application, entonces su clase de prueba podría encontrar el @SpringBootApplication(y en ese caso, el @SpringBootConfiguration).

Si la aplicación residía en una rama diferente de la jerarquía de paquetes, sin embargo, al igual com.example.application.Application, sería no encontrarlo.

Ejemplo

Considere el siguiente proyecto de Maven:

my-test-project
  +--pom.xml
  +--src
    +--main
      +--com
        +--example
          +--Application.java
    +--test
      +--com
        +--example
          +--test
            +--JpaTest.java

Y luego el siguiente contenido en Application.java:

package com.example;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Seguido por el contenido de JpaTest.java:

package com.example.test;

@RunWith(SpringRunner.class)
@DataJpaTest
public class JpaTest {

    @Test
    public void testDummy() {
    }
}

Todo debería estar funcionando. Si crea una nueva carpeta dentro de la src/main/com/examplellamada appy luego la coloca Application.javadentro (y actualiza la packagedeclaración dentro del archivo), ejecutar la prueba le dará el siguiente error:

java.lang.IllegalStateException: no se puede encontrar una @SpringBootConfiguration, debe usar @ContextConfiguration o @SpringBootTest (classes = ...) con su prueba

Thomas Kåsene
fuente
1
Saludos, gracias por ofrecer una solución Estoy usando la configuración del paquete Maven, con un paquete diferente para las pruebas y el código de la aplicación. Si interpreto bien, ¿qué está diciendo es que tengo que dirigir mi paquete de prueba a la clase de aplicación? y luego encontrará la SpringConfiguration?
Thomas Billet
Si por "experto paquete" que quiere decir "módulo", entonces sí, el módulo en el que su clase de prueba es tiene que depender del módulo que Applicationse encuentra en. Sin embargo, si usted se refiere src/mainy src/test, a continuación, esas carpetas no son parte del paquete jerarquía. Quizás sea mejor que solo actualice su pregunta con una captura de pantalla o una explicación de cómo es la estructura de su proyecto.
Thomas Kåsene
Acabo de resolver el problema como dijiste. Después de buscar en Google, encontré la estructura de paquete de primavera sugerida y los refactoré. Ahora las pruebas se ejecutan como se esperaba. Muchas gracias
Thomas Billet
Muy bien, es bueno saberlo! Actualicé la respuesta con un ejemplo más completo de todos modos.
Thomas Kåsene
3
+ - test + - com + - example + - JpaTest.java también funciona
user674158
106

La configuración se adjunta a la clase de aplicación, por lo que lo siguiente configurará todo correctamente:

@SpringBootTest(classes = Application.class)

Ejemplo del proyecto JHipster aquí .

mrts
fuente
Esta parece ser la solución perfecta. No necesito mover ninguna clase o carpeta.
Abhishek Aggarwal
21

Vale la pena verificar si ha refactorizado el nombre del paquete de su clase principal anotado con @SpringBootApplication. En ese caso, el caso de prueba debe estar en un paquete apropiado; de lo contrario, lo buscará en el paquete anterior. Este fue el caso para mí.

Mohammed Rafeeq
fuente
12

Además de lo que dijo Thomas Kåsene, también puede agregar

@SpringBootTest(classes=com.package.path.class)

a la anotación de prueba para especificar dónde debe buscar la otra clase si no desea refactorizar su jerarquía de archivos. Esto es lo que el mensaje de error sugiere al decir:

Unable to find a @SpringBootConfiguration, you need to use 
@ContextConfiguration or @SpringBootTest(classes=...) ...
Cameron Gagnon
fuente
¡Esta es una respuesta muy valiosa! Gracias @cameron!
Lance Kind
6

En mi caso, los paquetes eran diferentes entre las clases Aplicación y Prueba

package com.example.abc;
...
@SpringBootApplication
public class ProducerApplication {

y

package com.example.abc_etc;
...
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProducerApplicationTest {

Después de hacerlos aceptar, las pruebas se ejecutaron correctamente.

Mella
fuente
5

Funciona para mi

el nombre del paquete de la clase de prueba anterior se cambia al mismo que el nombre del paquete de la clase normal.

cambiar a esto

Hang Gao
fuente
3

El segmento de prueba proporcionado en Spring Boot 1.4 trajo capacidades de prueba orientadas a funciones .

Por ejemplo,

@JsonTest proporciona un entorno Jackson simple para probar la serialización y deserialización de json.

@WebMvcTest proporciona un entorno web simulado, puede especificar la clase de controlador para la prueba e inyectar el MockMvc en la prueba.

@WebMvcTest(PostController.class)
public class PostControllerMvcTest{

    @Inject MockMvc mockMvc;

}

@DataJpaTest preparará una base de datos integrada y proporcionará un entorno JPA básico para la prueba.

@RestClientTest proporciona un entorno de cliente REST para la prueba, especialmente RestTemplateBuilder, etc.

Estas anotaciones no están compuestas con SpringBootTest, se combinan con una serie de AutoconfigureXXXy unas @TypeExcludesFilteranotaciones.

Echa un vistazo a @DataJpaTest.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest {}

Puede agregar su anotación @AutoconfigureXXX para anular la configuración predeterminada.

@AutoConfigureTestDatabase(replace=NONE)
@DataJpaTest
public class TestClass{
}

Echemos un vistazo a su problema,

  1. No mezcle @DataJpaTesty @SpringBootTest, como se dijo anteriormente @DataJpaTest, construirá la configuración a su manera (por ejemplo, de forma predeterminada, intentará preparar un H2 incrustado) a partir de la herencia de configuración de la aplicación. @DataJpaTestestá designado para el corte de prueba .
  2. Si desea personalizar la configuración de @DataJpaTest, lea esta entrada de blog oficial de Spring.io para este tema, (un poco tedioso).
  3. Divida las configuraciones en configuraciones Applicationmás pequeñas por características, tales como WebConfig, DataJpaConfigetc. Una configuración con todas las funciones (web mixta, datos, seguridad, etc.) también hizo que sus pruebas basadas en el segmento de prueba fallaran. Verifique las muestras de prueba en mi muestra .
Hantsy
fuente
1

Creo que la mejor solución para este problema es alinear la estructura de carpetas de pruebas con la estructura de carpetas de la aplicación.

Tuve el mismo problema causado por la duplicación de mi proyecto desde un proyecto de estructura de carpetas diferente.

Si su proyecto de prueba y su proyecto de aplicación tendrán la misma estructura, no será necesario que agregue anotaciones especiales a sus clases de prueba y todo funcionará como está.

plata
fuente
Tuve el mismo error y finalmente descubrí que el nombre del paquete para la clase de prueba tenía una "regla" de error tipográfico en lugar de "reglas". Después de corregir el nombre del paquete, el error desapareció.
Gopal Bairwa
1

Cuando todas las clases estaban en el mismo paquete, las clases de prueba funcionaban. Tan pronto como moví todas las clases de Java a un paquete diferente para mantener la estructura adecuada del proyecto, recibí el mismo error.

Lo resolví proporcionando mi nombre de clase principal en la clase de prueba como se muestra a continuación.

@SpringBootTest(classes=JunitBasicsApplication.class)
SumataPatil
fuente
1

Tuve el mismo problema y lo resolví agregando una clase vacía anotada SpringBootApplicationen el paquete raíz de la carpeta src / test / java

package org.enricogiurin.core;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CoreTestConfiguration {}
Enrico Giurin
fuente
0

En mi caso,
asegúrese de que su ( test packagenombre ) YourApplicationTestssea ​​equivalente al ( main packagenombre ).

ahmednabil88
fuente
-2
import org.junit.Test;
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.web.servlet.AutoConfigureWebMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;



@RunWith(SpringRunner.class)
@DataJpaTest
@SpringBootTest
@AutoConfigureWebMvc
public class RepoTest {

    @Autowired
    private ThingShiftDetailsRepository thingShiftDetailsRepo;

    @Test
    public void findThingShiftDetails() {
            ShiftDetails details = new ShiftDetails();
            details.setThingId(1);

            thingShiftDetailsRepo.save(details);

            ShiftDetails dbDetails = thingShiftDetailsRepo.findByThingId(1);
            System.out.println(dbDetails);
    }
}

Las anotaciones anteriores funcionaron bien para mí. Estoy usando arranque de primavera con JPA.

Umesh G
fuente