web-dev-qa-db-fra.com

Spring Boot ComponentScan excludeFIlters not exclusive

J'ai un SimpleTest:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SimpleTestConfig.class)
public class SimpleTest {
    @Test
    public void test() {
        assertThat(true);
    }
}

et un configuration pour ce test:

@SpringBootApplication
@ComponentScan(basePackageClasses = {
        SimpleTestConfig.class,
        Application.class
},
        excludeFilters = @ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE,
                classes = Starter.class))
public class SimpleTestConfig {
}

J'essaie d'exclure la classe Starter

package application.starters;

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

@Component
public class Starter {
    @PostConstruct
    public void init(){
        System.out.println("initializing");
    }
}

Et la classe Application ressemble à ceci:

package application;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import static org.springframework.boot.SpringApplication.run;

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

Mais pour une raison très étrange, la classe Starter est toujours en cours d'initialisation.

Quelqu'un peut-il expliquer pourquoi le ComponentScan excludeFilters n'exclut pas ma classe Starter?

11
Daniel Taub

Chaque analyse de composant effectue un filtrage individuel. Pendant que vous excluez Starter.class De SimpleTestConfig, SimpleTestConfig initialise Application, qui possède son propre @ComponentScan Sans exclure Starter. La manière propre d'utiliser ComponentScan consiste pour chaque ComponentScan à analyser des packages distincts, de sorte que chaque filtre fonctionne correctement. Lorsque 2 ComponentScans distincts analysent le même package (comme dans vos tests), cela ne fonctionne pas.

Une façon de tromper cela est de fournir un bean simulé Starter:

import org.springframework.boot.test.mock.mockito.MockBean;

public class SimpleTest {
    @MockBean
    private Starter myTestBean;
    ...
}

Spring utilisera cette maquette au lieu de la classe réelle, donc la méthode @PostConstruct Ne sera pas appelée.

Autres solutions courantes:

  • N'utilisez pas directement Application.class Dans un test unitaire
  • Utilisez le profil Spring et des annotations telles que @Profile("!TEST") sur la classe Starter
  • Utilisez une annotation Spring Boot @ConditionalOn... Sur la classe Starter
17
tkruse

Vous pouvez définir un filtre d'analyse de composant personnalisé pour l'exclure.

Un exemple de code sera comme:

@SpringBootApplication()
@ComponentScan(excludeFilters=@Filter(type = FilterType.REGEX, pattern="com.wyn.applications.starter.Starter*"))
public class SimpleTestConfig {

}

Cela fonctionne pour moi.

Pour en savoir plus, allez sur ce blog .

0
Yogi

@ SpringBootApplication , selon la documentation Spring, la fonctionnalité combinée de: @ Configuration , @ EnableAutoConfiguration et @ ComponentScan en une seule notation.

Essayez d'abord sans affiner l'analyse de votre package (sans le filtre basePackages).

@SpringBootApplication(exclude= {Foo.class})
public class MySpringConfiguration {}
0
dorony