Comment utiliser @ComponentScan avec test spécifique ContextConfigurations dans SpringJunit4TestRunner?

Je suis en train de tester un Ressort de Démarrage de l'application. J'ai test de plusieurs classes, dont chacune a besoin d'un ensemble différent de moqués ou autrement personnalisés haricots.

Voici un croquis de l'installation:

src/main/java:

package com.example.myapp;

@SpringBootApplication
@ComponentScan(
        basePackageClasses = {
                MyApplication.class,
                ImportantConfigurationFromSomeLibrary.class,
                ImportantConfigurationFromAnotherLibrary.class})
@EnableFeignClients
@EnableHystrix
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

package com.example.myapp.feature1;

@Component
public class Component1 {
    @Autowired
    ServiceClient serviceClient;

    @Autowired
    SpringDataJpaRepository dbRepository;

    @Autowired
    ThingFromSomeLibrary importantThingIDontWantToExplicitlyConstructInTests;

    //methods I want to test...
}

src/test/java:

package com.example.myapp;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class Component1TestWithFakeCommunication {

    @Autowired
    Component1 component1; //<-- the thing we're testing. wants the above mock implementations of beans wired into it.

    @Autowired
    ServiceClient mockedServiceClient;

    @Configuration
    static class ContextConfiguration {
        @Bean
        @Primary
        public ServiceClient mockedServiceClient() {
            return mock(ServiceClient.class);
        }
    }

    @Before
    public void setup() {
        reset(mockedServiceClient);
    }

    @Test
    public void shouldBehaveACertainWay() {
        //customize mock, call component methods, assert results...
    }
}

package com.example.myapp;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class Component1TestWithRealCommunication {

    @Autowired
    Component1 component1; //<-- the thing we're testing. wants the real implementations in this test.

    @Autowired
    ServiceClient mockedServiceClient;

    @Before
    public void setup() {
        reset(mockedServiceClient);
    }

    @Test
    public void shouldBehaveACertainWay() {
        //call component methods, assert results...
    }
}

Le problème avec la configuration ci-dessus est que le composant d'analyse configuré dans MyApplication ramasse Component1TestWithFakeCommunication.ContextConfiguration, si je reçois une maquette ServiceClient même dans Component1TestWithRealCommunication où je veux le vrai ServiceClient mise en œuvre.

Bien que je pourrais utiliser @Autocâblés constructeurs et mettre en place les composants moi-même dans les deux tests, il ya une quantité suffisante de trucs avec des réglages compliqués que je préférerais avoir le Printemps TestContext mis en place pour moi (par exemple, Spring Data JPA dépôts, les composants de bibliothèques en dehors de l'application qui tirent les haricots du Printemps contexte, etc.). Imbrication d'un Printemps de configuration à l'intérieur de l'épreuve qui peut localement remplacer certaines bean définitions dans le Printemps contexte se sent comme il doit être propre façon de le faire; le seul inconvénient est que ces imbriquée configurations finissent par toucher tout le Printemps TestContext tests de la base de leur configuration sur MyApplication (le composant qui scanne le package de l'application).

Comment puis-je modifier mon installation, donc je suis toujours un "la plupart du temps réel" Printemps contexte pour mes tests avec seulement quelques localement remplacé les haricots dans chaque classe de test?

OriginalL'auteur Jonathan Fuerth | 2016-09-02