Impossible de trouver une @SpringBootConfiguration lors d'un JpaTest

186

Je suis nouveau dans les frameworks (je viens de passer le cours) et c'est la première fois que j'utilise Spring Boot.

J'essaie d'exécuter un simple test Junit pour voir si mes CrudRepositories fonctionnent effectivement.

L'erreur que je continue de recevoir est:

Impossible de trouver un @SpringBootConfiguration, vous devez utiliser @ContextConfiguration ou @SpringBootTest (classes = ...) avec votre test java.lang.IllegalStateException

Spring Boot ne se configure-t-il pas?

Ma classe de test:

@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);

 }

Mon démarreur d'application 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);         

        }
    }

Mon référentiel:

public interface AccountRepository extends CrudRepository<Account,Long> {

    public Account findByUsername(String username);

    }
}
Thomas Billet
la source

Réponses:

264

En effet, Spring Boot s'installe pour la plupart. Vous pouvez probablement déjà vous débarrasser d'une grande partie du code que vous avez publié, en particulier dans Application.

J'aurais aimé que vous ayez inclus les noms de package de toutes vos classes, ou du moins ceux pour Applicationet JpaTest. Le truc @DataJpaTestet quelques autres annotations, c'est qu'ils recherchent un@SpringBootConfiguration annotation dans le package actuel, et s'ils ne peuvent pas la trouver là, ils traversent la hiérarchie du package jusqu'à ce qu'ils la trouvent.

Par exemple, si le nom complet de votre classe de test était com.example.test.JpaTestet celui de votre application l'était com.example.Application, alors votre classe de test serait en mesure de trouver le @SpringBootApplication(et là, le@SpringBootConfiguration ).

Cependant, si l'application résidait dans une branche différente de la hiérarchie des packages com.example.application.Application, elle ne la trouverait pas.

Exemple

Considérez le projet Maven suivant:

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

Et puis le contenu suivant dans Application.java:

package com.example;

@SpringBootApplication
public class Application {

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

Suivi du contenu de JpaTest.java:

package com.example.test;

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

    @Test
    public void testDummy() {
    }
}

Tout devrait fonctionner. Si vous créez un nouveau dossier à l'intérieur src/main/com/exampleappelé app, puis mettez-le à l' Application.javaintérieur (et mettez à jour la packagedéclaration dans le fichier), l'exécution du test vous donnera l'erreur suivante:

java.lang.IllegalStateException: Impossible de trouver un @SpringBootConfiguration, vous devez utiliser @ContextConfiguration ou @SpringBootTest (classes = ...) avec votre test

Thomas Kåsene
la source
1
Salutations, merci d'avoir proposé une solution Am utilisant la configuration des paquets Maven, avec un package différent pour les tests et le code de l'application. Si j'interprète correctement ce que vous dites, c'est que je dois diriger mon package de test vers la classe Application? et puis il trouvera le SpringConfiguration?
Thomas Billet
Si par "maven packet" vous voulez dire "module", alors oui, le module dans lequel se trouve votre classe de test doit dépendre du module qui se Applicationtrouve. Si, cependant, vous voulez dire src/mainet src/test, alors ces dossiers ne font pas partie du package hiérarchie. Vous feriez peut-être mieux de simplement mettre à jour votre question avec une capture d'écran ou une explication de la structure de votre projet.
Thomas Kåsene
Je viens de résoudre le problème comme vous l'avez dit. après quelques recherches sur Google, j'ai trouvé la structure de paquet de ressort suggérée et je les ai toutes refactorisées. Maintenant, les tests se déroulent comme prévu. Merci beaucoup
Thomas Billet
Très bien, bon à savoir! J'ai quand même mis à jour la réponse avec un exemple plus complet.
Thomas Kåsene
3
+ - test + - com + - exemple + - JpaTest.java fonctionne également
user674158
106

La configuration est attachée à la classe d'application, donc ce qui suit va tout configurer correctement:

@SpringBootTest(classes = Application.class)

Exemple du projet JHipster ici .

mrts
la source
Cela semble être la solution parfaite. Je n'ai pas besoin de déplacer de classe ou de dossier.
Abhishek Aggarwal le
21

Il vaut la peine de vérifier si vous avez refactoré le nom du package de votre classe principale annoté avec @SpringBootApplication. Dans ce cas, le cas de test doit être dans un package approprié, sinon il le recherchera dans l'ancien package. c'était le cas pour moi.

Mohammed Rafeeq
la source
12

En plus de ce que Thomas Kåsene a dit, vous pouvez également ajouter

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

à l'annotation de test pour spécifier où elle doit rechercher l'autre classe si vous ne souhaitez pas refactoriser votre hiérarchie de fichiers. Voici ce à quoi le message d'erreur fait allusion en disant:

Unable to find a @SpringBootConfiguration, you need to use 
@ContextConfiguration or @SpringBootTest(classes=...) ...
Cameron Gagnon
la source
C'est une réponse très précieuse! Merci @cameron!
Lance Kind
6

Dans mon cas, les packages étaient différents entre les classes Application et Test

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

et

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

Après les avoir acceptés, les tests se sont déroulés correctement.

pseudo
la source
5

Ça marche pour moi

le nom de package de la classe de test ci-dessus est changé pour le même que le nom de package de la classe normale.

changer cela

accrocher gao
la source
3

La tranche d'essai prévu au printemps de démarrage 1.4 apporté fonctionnalité des capacités de test orientées.

Par exemple,

@JsonTest fournit un environnement Jackson simple pour tester la sérialisation et la désérialisation json.

@WebMvcTest fournit un environnement Web simulé, il peut spécifier la classe de contrôleur pour le test et injecter le MockMvc dans le test.

@WebMvcTest(PostController.class)
public class PostControllerMvcTest{

    @Inject MockMvc mockMvc;

}

@DataJpaTest préparera une base de données intégrée et fournira un environnement JPA de base pour le test.

@RestClientTest fournit un environnement client REST pour le test, en particulier RestTemplateBuilder, etc.

Ces annotations ne sont pas composées avec SpringBootTest, elles sont combinées avec une série de AutoconfigureXXXet un@TypeExcludesFilter annotations .

Jetez un oeil à @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 {}

Vous pouvez ajouter votre annotation @AutoconfigureXXX pour remplacer la configuration par défaut.

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

Jetons un œil à votre problème,

  1. Ne mélangez pas @DataJpaTestet @SpringBootTest, comme indiqué ci @DataJpaTest- dessus , construira la configuration à sa manière (par exemple, par défaut, il essaiera de préparer un H2 intégré à la place) à partir de l'héritage de configuration de l'application. @DataJpaTestest désigné pour la tranche de test .
  2. Si vous souhaitez personnaliser la configuration de @DataJpaTest, veuillez lire cet article de blog officiel de Spring.io pour ce sujet, (un peu fastidieux).
  3. Divisez les configurations en configurations Applicationplus petites par fonctionnalités, telles que WebConfig, DataJpaConfigetc. Une configuration complète (Web mixte, données, sécurité, etc.) a également provoqué l'échec de vos tests basés sur des tranches de test . Vérifiez les échantillons de test dans mon échantillon .
Hantsy
la source
1

Je pense que la meilleure solution pour ce problème est d'aligner la structure de vos dossiers de tests avec la structure de dossiers de l'application.

J'ai eu le même problème qui a été causé par la duplication de mon projet à partir d'un autre projet de structure de dossiers.

si votre projet de test et votre projet d'application auront la même structure, vous ne serez pas obligé d'ajouter des annotations spéciales à vos classes de tests et tout fonctionnera tel quel.

argent
la source
J'ai eu la même erreur et j'ai finalement compris que le nom du paquet pour la classe de test avait une faute de frappe "règle" à la place de "règles". Après avoir corrigé le nom du package, l'erreur a disparu.
Gopal Bairwa
1

Lorsque toutes les classes étaient dans le même package, les classes de test fonctionnaient. Dès que j'ai déplacé toutes les classes java vers un package différent pour maintenir une structure de projet appropriée, j'obtenais la même erreur.

Je l'ai résolu en fournissant mon nom de classe principale dans la classe de test comme ci-dessous.

@SpringBootTest(classes=JunitBasicsApplication.class)
SumataPatil
la source
1

J'ai eu le même problème et j'ai résolu en ajoutant une classe vide annotée SpringBootApplicationdans le package racine du dossier src / test / java

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

@SpringBootApplication
public class CoreTestConfiguration {}
Enrico Giurin
la source
0

Dans mon cas,
assurez-vous que votre ( test packagenom ) de YourApplicationTestsest équivalent au ( main packagenom ).

ahmednabil88
la source
-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);
    }
}

Les annotations ci-dessus ont bien fonctionné pour moi. J'utilise Spring Boot avec JPA.

Umesh G
la source