2015-10-23 17 views
7

Ho letto molti articoli su come deridere il bean di Spring e i loro campi autowired. Ma non c'è nulla che io possa trovare sulle liste di fagioli autowired.Come prendere in giro una lista autorizzata di bean Spring?

problema concreto

Ho una classe chiamata FormValidatorManager. Questo ciclo di classe attraverso diversi validatori che implementa IFormValidator.

@Component 
public class FormValidatorManager implements IValidatorManager { 

    @Autowired 
    private List<IFormValidator> validators; 

    /* 
    * (non-Javadoc) 
    * 
    * @see 
    * com.sagemcom.esm.vision.business.validator.IFormValidator#validate(com 
    * .sagemcom.esm.vision.model.tablesdefinition.ColumnDTO, java.lang.String) 
    */ 
    @Override 
    public final IFieldError validate(ColumnDTO columnToValidate, String sentValue) { 
     String loweredColName = columnToValidate.getName().toLowerCase(); 
     IFieldError errorField = new FieldError(loweredColName); 

     for (IEsmFormValidator validator : validators) { 
      List<String> errrorsFound = validator.validate(columnToValidate, sentValue); 

      //les erreurs ne doivent pas être cumulées. 
      if(CollectionUtils.isNotEmpty(errrorsFound)){ 
       errorField.addErrors(errrorsFound); 
       break; 
      } 
     } 

     return errorField; 
    } 
} 

Vorrei testare questo corso. Ma non riesco a trovare un modo per deridere la proprietà validators.

Quello che ho provato

Dal IFormValidators sono Singleton, ho cercato di deridere diverse istanze di questi fagioli sperando loro di essere riflesse in FormValidatorManager.validators ma senza successo.

Quindi, ho provato a creare un elenco di IFormValidators che è stato annotato come @Mock. Avviando manualmente il List, speravo che initMocks() inserisse l'elenco creato. Era ancora senza successo.

Ecco il mio ultimo tentativo:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations={"classpath:spring/test-validator-context.xml"}) 
public class FormValidatorManagerTest { 

    @Mock 
    private RegexValidator regexValidator; 

    @Mock 
    private FormNotNullValidator notNullValidator; 

    @Mock 
    private FormDataTypeValidator dataValidator; 

    @InjectMocks 
    private FormValidatorManager validatorManager; 

    @Mock 
    private List<IEsmFormValidator> validators = new ArrayList<IEsmFormValidator>(); 

    @Mock 
    private ColumnDTO columnDTO; 

    @Before 
    public void init() { 

     validators.add(notNullValidator); 
     validators.add(regexValidator); 
     validators.add(dataValidator); 

     MockitoAnnotations.initMocks(this); 

     Mockito.when(columnDTO.getTitle()).thenReturn("Mock title"); 
     Mockito.when(columnDTO.getName()).thenReturn("Mock name"); 
    } 



    @Test 
    public void testNoErrorFound(){ 
     mockValidator(notNullValidator, new ArrayList<String>()); 
     mockValidator(regexValidator, new ArrayList<String>()); 
     mockValidator(dataValidator, new ArrayList<String>()); 

     IFieldError fieldErrors = validatorManager.validate(columnDTO, "Not null value"); 

     Assert.assertEquals(0, fieldErrors.getErrors().size()); 

     verifyNumberOfValidateCalls(regexValidator, Mockito.atMost(1)); 
     verifyNumberOfValidateCalls(dataValidator, Mockito.atMost(1)); 
     verifyNumberOfValidateCalls(notNullValidator, Mockito.atMost(1)); 
    } 



    private void mockValidator(IFormValidator validator, List<String> listToReturn){ 
     Mockito.when(validator.validate(Mockito.any(ColumnDTO.class), Mockito.anyString())).thenReturn(listToReturn); 
    } 

    private void verifyNumberOfValidateCalls(IFormValidator validator, VerificationMode verifMode){ 
     Mockito.verify(validator, verifMode).validate(Mockito.any(ColumnDTO.class), Mockito.anyString()); 
    } 
} 

Un NPE è gettato in IFormValidator.validate() cui ho thougth verrebbe deriso. L'implementazione concreta non dovrebbe essere chiamata.

Questo porta a un comportamento davvero negativo poiché alcuni dei miei test su quella classe sono falsi positivi mentre altri falliscono completamente.

Sto cercando di capire come creare un elenco di bean autowired pur avendo la possibilità di simulare implementazioni specifiche.

Avete un'idea di avvio della soluzione?

saluti

+0

Come vi aspettate '@ Mock' e' @ Autowired' sul singolo campo per lavorare? Vuoi deriderlo o cablato automaticamente? Anche la creazione di un elenco nel test e sperando in primavera di rilevarlo non accadrà mai. Crea mock nella tua configurazione di primavera invece delle tue classi, usa il metodo di produzione 'mock' di' Mockito' per quello. –

+0

In realtà lo voglio prendere in giro, ma visto che è un fagiolo primaverile, non dovrei nemmeno essere autowired?In realtà ho provato a rimuovere l'autowired, ma non ha funzionato altrettanto bene. È anche peggio visto che i validatori sono nulli e non sono derisi. –

+0

puoi usare @Autowired sopra il costruttore. Quindi in prova si potevano passare i validatori come parametri del costruttore alla classe testata. – freakman

risposta

9

ho finalmente capito che fuori ...

A volte, chiedendo una domanda può dare un approccio migliore ai vostri problemi: p

Il problema è che è stato che collega i validatori per la lista prima di essere derisi. I validatori erano quindi nulli e nessun riferimento poteva essere aggiornato quando MockitAnnotations.initMocks(this).

Inoltre, per evitare problemi di iteratore su List, ho dovuto utilizzare @Spy anziché @Mock.

ecco la soluzione Finaly:

@Mock 
private EsmRegexValidator regexValidator; 

@Mock 
private EsmFormNotNullValidator notNullValidator; 

@Mock 
private EsmFormDataTypeValidator dataValidator; 

@InjectMocks 
private EsmFormValidatorManager validatorManager; 

@Spy 
private List<IEsmFormValidator> validators = new ArrayList<IEsmFormValidator>(); 

@Mock 
private ColumnDTO columnDTO; 

@Before 
public void init() { 

    MockitoAnnotations.initMocks(this); 

    validators.add(notNullValidator); 
    validators.add(regexValidator); 
    validators.add(dataValidator); 

    Mockito.when(columnDTO.getTitle()).thenReturn("Mock title"); 
    Mockito.when(columnDTO.getName()).thenReturn("Mock name"); 
} 
Problemi correlati