Não foi possível encontrar um @SpringBootConfiguration ao fazer um JpaTest

185

Eu sou novo em frameworks (acabei de passar a classe) e esta é minha primeira vez usando o Spring Boot.

Estou tentando executar um teste Junit simples para ver se meus CrudRepositories estão realmente funcionando.

O erro que continuo recebendo é:

Não foi possível encontrar um @SpringBootConfiguration, você precisa usar @ContextConfiguration ou @SpringBootTest (classes = ...) com seu teste java.lang.IllegalStateException

O Spring Boot não se configura?

Minha classe de teste:

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

 }

O iniciador do aplicativo My 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);         

        }
    }

Meu Repositório:

public interface AccountRepository extends CrudRepository<Account,Long> {

    public Account findByUsername(String username);

    }
}
Thomas Billet
fonte

Respostas:

264

De fato, o Spring Boot se configura na maior parte do tempo. Provavelmente você já pode se livrar de grande parte do código publicado, especialmente no Application.

Eu gostaria que você tivesse incluído os nomes dos pacotes de todas as suas classes, ou pelo menos os de Applicatione JpaTest. O problema @DataJpaTeste algumas outras anotações é que elas procuram uma @SpringBootConfigurationanotação no pacote atual e, se não conseguem encontrá-la, percorrem a hierarquia do pacote até encontrá-la.

Por exemplo, se o nome completo da sua classe de teste fosse com.example.test.JpaTeste o nome do seu aplicativo fosse com.example.Application, sua classe de teste seria capaz de encontrar o @SpringBootApplication(e nisto, o @SpringBootConfiguration).

Se o aplicativo residisse em uma ramificação diferente da hierarquia de pacotes, no entanto com.example.application.Application, ele não o encontraria.

Exemplo

Considere o seguinte projeto Maven:

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

E então o seguinte conteúdo em Application.java:

package com.example;

@SpringBootApplication
public class Application {

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

Seguido pelo conteúdo de JpaTest.java:

package com.example.test;

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

    @Test
    public void testDummy() {
    }
}

Tudo deve estar funcionando. Se você criar uma nova pasta src/main/com/examplechamada dentro appe depois colocar a sua Application.javadentro (e atualizar a packagedeclaração dentro do arquivo), a execução do teste fornecerá o seguinte erro:

java.lang.IllegalStateException: não foi possível encontrar uma @SpringBootConfiguration, você precisa usar @ContextConfiguration ou @SpringBootTest (classes = ...) com seu teste

Thomas Kåsene
fonte
1
Saudações, obrigado por oferecer uma solução. Estou usando a configuração de pacotes Maven, com um pacote diferente para testes e o código do aplicativo. Se eu interpretar corretamente o que você está dizendo, é que devo direcionar meu pacote de teste para a classe Application? e então ele encontrará o SpringConfiguration?
Thomas Billet
Se por "pacote maven" você quer dizer "módulo", sim, o módulo em que está sua classe de teste deve depender do módulo em que Applicationestá. Se, no entanto, você quer dizer com src/maine src/test, essas pastas não fazem parte do pacote hierarquia. Talvez você esteja melhor atualizando sua pergunta com uma captura de tela ou uma explicação de como é a estrutura do seu projeto.
Thomas Kåsene
Acabei de resolver o problema como você disse. depois de pesquisar no Google, encontrei a estrutura sugerida de pacotes de primavera e refatorei todos eles. Agora os testes são executados conforme o esperado. Muito obrigado
Thomas Billet
Tudo bem, é bom saber! Atualizei a resposta com um exemplo mais completo de qualquer maneira.
Thomas Kåsene
3
+ - teste + - com + - exemplo + - JpaTest.java também trabalho
user674158
106

A configuração está anexada à classe do aplicativo, portanto, o seguinte definirá tudo corretamente:

@SpringBootTest(classes = Application.class)

Exemplo do projeto JHipster aqui .

Mrts
fonte
Esta parece ser a solução perfeita. Não preciso mover nenhuma classe ou pasta.
Abhishek Aggarwal
21

Vale a pena verificar se você anotou o nome do pacote refatorado da sua classe principal @SpringBootApplication. Nesse caso, o testcase deve estar em um pacote apropriado, caso contrário, ele estará procurando no pacote mais antigo. esse foi o meu caso.

Mohammed Rafeeq
fonte
11

Além do que Thomas Kåsene disse, você também pode adicionar

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

à anotação de teste para especificar onde deve procurar a outra classe se você não deseja refatorar sua hierarquia de arquivos. É para isso que a mensagem de erro sugere dizendo:

Unable to find a @SpringBootConfiguration, you need to use 
@ContextConfiguration or @SpringBootTest(classes=...) ...
Cameron Gagnon
fonte
Esta é uma resposta muito valiosa! Obrigado @cameron!
Lance Kind
6

No meu caso, os pacotes eram diferentes entre as classes Application e Test

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

e

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

Depois de fazê-los concordar, os testes foram executados corretamente.

usuario
fonte
5

Funciona para mim

o nome do pacote da classe de teste acima é alterado para o mesmo que o nome do pacote da classe normal.

mude para isso

pendure gao
fonte
3

A fatia de teste fornecida no Spring Boot 1.4 trouxe o recurso teste orientados a recursos.

Por exemplo,

@JsonTest fornece um ambiente Jackson simples para testar a serialização e desserialização do json.

O @WebMvcTest fornece um ambiente web simulado, pode especificar a classe do controlador para teste e injetar o MockMvc no teste.

@WebMvcTest(PostController.class)
public class PostControllerMvcTest{

    @Inject MockMvc mockMvc;

}

@DataJpaTest prepara um banco de dados incorporado e fornece um ambiente JPA básico para o teste.

@RestClientTest fornece o ambiente do cliente REST para o teste, especialmente o RestTemplateBuilder etc.

Essas anotações não são compostas com SpringBootTest, elas são combinadas com uma série de AutoconfigureXXXe um@TypeExcludesFilter anotações.

Dê uma olhada @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 {}

Você pode adicionar sua anotação @AutoconfigureXXX para substituir a configuração padrão.

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

Vamos dar uma olhada no seu problema,

  1. Não misture @DataJpaTeste @SpringBootTest, como dito acima @DataJpaTest, construirá a configuração de seu próprio modo (por exemplo, por padrão, ele tentará preparar um H2 incorporado) a partir da herança de configuração do aplicativo. @DataJpaTesté designado para fatia de teste .
  2. Se você deseja personalizar a configuração @DataJpaTest, leia esta entrada oficial do blog da Spring.io para este tópico (um pouco tedioso).
  3. Divida as configurações em configurações Applicationmenores por recursos, como WebConfig, DataJpaConfigetc. Uma configuração completa (web mista, dados, segurança etc.) também causou falhas nos testes com base na fatia de teste . Verifique as amostras de teste na minha amostra .
Hantsy
fonte
1

Eu acho que a melhor solução para esse problema é alinhar a estrutura de pastas de testes com a estrutura de pastas do aplicativo.

Eu tive o mesmo problema causado pela duplicação do meu projeto de um projeto de estrutura de pastas diferente.

se seu projeto de teste e seu projeto de aplicativo tiverem a mesma estrutura, não será necessário adicionar anotações especiais às suas classes de testes e tudo funcionará como está.

prata
fonte
Eu tive o mesmo erro e finalmente descobri que o nome do pacote para a classe de teste tinha um erro de digitação "regra" no lugar de "regras". Depois de corrigir o nome do pacote, o erro desapareceu.
Gopal Bairwa 29/10/19
1

Quando todas as classes estavam no mesmo pacote, as classes de teste estavam funcionando. Assim que mudei todas as classes java para um pacote diferente, para manter a estrutura adequada do projeto, estava recebendo o mesmo erro.

Eu o resolvi fornecendo meu nome de classe principal na classe de teste, como abaixo.

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

Eu tive o mesmo problema e resolvi adicionando uma classe vazia anotada SpringBootApplicationno pacote raiz da pasta src / test / java

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

@SpringBootApplication
public class CoreTestConfiguration {}
Enrico Giurin
fonte
0

No meu caso,
verifique se o seu ( test packagenome ) YourApplicationTestsé equivalente ao ( main packagenome ).

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

As anotações acima funcionaram bem para mim. Estou usando a bota primavera com JPA.

Umesh G
fonte