web-dev-qa-db-fra.com

Spring JUnit: comment simuler un composant autowired dans un composant autowired

Je souhaite tester un composant Spring et ce composant possède un attribut autowired que je dois modifier aux fins des tests unitaires. Le problème est que la classe utilise le composant autowired dans la méthode post-construction, je ne suis donc pas en mesure de le remplacer (c'est-à-dire via ReflectionTestUtils) avant son utilisation réelle.

Comment devrais-je faire ça?

C'est la classe que je veux tester:

@Component
public final class TestedClass{

    @Autowired
    private Resource resource;

    @PostConstruct
    private void init(){
        //I need this to return different result
        resource.getSomething();
    }
}

Et voici la base d'un cas de test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= "classpath:applicationContext.xml")
public class TestedClassTest{

    @Autowired
    private TestedClass instance;

    @Before
    private void setUp(){
        //this doesn't work because it's executed after the bean is instantiated
        ReflectionTestUtils.setField(instance, "resource", new Resource("something"));
    }
}

Existe-t-il un moyen de remplacer la ressource par autre chose avant que la méthode postconstruct soit appelée? Vous voulez dire au coureur Spring JUnit d'autowire une instance différente?

53
NeplatnyUdaj

Vous pouvez fournir un nouveau fichier testContext.xml dans lequel le fichier @Autowired Le bean que vous définissez est du type dont vous avez besoin pour votre test.

9
phury

Vous pouvez utiliser Mockito . Je ne suis pas sûr avec PostConstruct en particulier, mais cela fonctionne généralement:

// Create a mock of Resource to change its behaviour for testing
@Mock
private Resource resource;

// Testing instance, mocked `resource` should be injected here 
@InjectMocks
@Resource
private TestedClass testedClass;

@Before
public void setUp() throws Exception {
    // Initialize mocks created above
    MockitoAnnotations.initMocks(this);
    // Change behaviour of `resource`
    when(resource.getSomething()).thenReturn("Foo");   
}
51
Anna Zubenko

Spring Boot 1.4 a introduit une annotation de test appelée @MockBean . Alors maintenant, se moquer et espionner les haricots du printemps est supporté nativement par Spring Boot.

18
luboskrnac

J'ai créé blog sur le sujet . Il contient également un lien vers le référentiel Github avec un exemple de travail.

L'astuce consiste à utiliser la configuration de test, où vous remplacez le haricot printanier d'origine par un faux. Vous pouvez utiliser @Primary et @Profile annotations pour cette astuce.

7
luboskrnac

Vous pouvez remplacer les définitions de haricots avec des mocks avec spring-reinject https://github.com/sgri/spring-reinject/

6
Sergey Grigoriev

Une autre approche des tests d’intégration consiste à définir une nouvelle classe de configuration et à la définir comme votre @ContextConfiguration. Dans la configuration, vous pourrez vous moquer de vos beans et vous devez également définir tous les types de beans que vous utilisez dans le flux test/s. Pour donner un exemple:

@RunWith(SpringRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class MockTest{
 @Configuration
 static class ContextConfiguration{
 // ... you beans here used in test flow
 @Bean
    public MockMvc mockMvc() {
        return MockMvcBuilders.standaloneSetup(/*you can declare your controller beans defines on top*/)
                .addFilters(/*optionally filters*/).build();
    }
 //Defined a mocked bean
 @Bean
    public MyService myMockedService() {
        return Mockito.mock(MyService.class);
    }
 }

 @Autowired
 private MockMvc mockMvc;

 @Autowired
 MyService myMockedService;

 @Before
 public void setup(){
  //mock your methods from MyService bean 
  when(myMockedService.myMethod(/*params*/)).thenReturn(/*my answer*/);
 }

 @Test
 public void test(){
  //test your controller which trigger the method from MyService
  MvcResult result = mockMvc.perform(get(CONTROLLER_URL)).andReturn();
  // do your asserts to verify
 }
}
3
Rzv Razvan