Ho un file di regole di drools che utilizza le classi di servizio nelle regole. Quindi una regola fa qualcosa di simile:L'annotazione transazionale evita che i servizi vengano derisi
eval (countryService.getCountryById (1)! = Null)
In un validationservice che viene annotato con @service e @Transactional (propagazione = Propagation.SUPPORTS) il file drools è usato in una statelessKnowledgebase e vengono aggiunti fatti che dovrebbero essere usati nella bava. Fatto ciò, viene richiamato session.execute (facts) e viene avviato il motore di regole.
Per testare le regole, desidero eseguire il stub del paeseService.getCountryById(). Nessun grosso problema con il mockito. Fatto questo per altri servizi che utilizzano un setup di drools e ha funzionato bene. Tuttavia in questo caso particolare il countryService non è stato soppresso e non sono riuscito a capire perché. Dopo aver trascorso un sacco di tempo e verificato il mio codice, ho scoperto che avere @Transactional al di sopra del servizio o la mancanza di questa annotazione ha fatto la differenza. Mancando la @Transaction ha fatto deridere il countryservice senza alcun problema, avendo il @transactional sul posto ha causato il fallimento di mockito (senza alcun errore o suggerimento) iniettando il mock in modo che fosse utilizzato l'oggetto countryservice originale.
La mia domanda è perché questa annotazione causa questo problema. Perché mockito non può iniettare i mock quando è impostato @Transactional? Ho notato che Mockito sta fallendo come quando il debug e ispezionare la countryService quando viene aggiunto come globale alla sessione sbava vedo la seguente differenza quando ho ispezionare il countryservice nel mio DebugWindow:
con @ transazionale: countryService ha il valore CountryService $$ $$ EnhancerByCGLIB b80dbb7b
senza @Transactional: countryService ha il valore CountryService $$ $$ EnhancerByMockitoWithCGLIB 27f34dc1
Inoltre con @t ransactional il mio punto di interruzione nel metodo countryservice getCountryById viene trovato e il debugger si ferma in quel punto di interruzione, ma senza @transactional il mio punto di interruzione viene saltato mentre mockito lo ignora.
ValidationService:
@Service
@Transactional(propagation=Propagation.SUPPORTS)
public class ValidationService
{
@Autowired
private CountryService countryService;
public void validateFields(Collection<Object> facts)
{
KnowledgeBase knowledgeBase = (KnowledgeBase)AppContext.getApplicationContext().getBean(knowledgeBaseName);
StatelessKnowledgeSession session = knowledgeBase.newStatelessKnowledgeSession();
session.setGlobal("countryService", countryService);
session.execute(facts);
}
E la classe di test:
public class TestForeignAddressPostalCode extends BaseTestDomainIntegration
{
private final Collection<Object> postalCodeMinLength0 = new ArrayList<Object>();
@Mock
protected CountryService countryService;
@InjectMocks
private ValidationService level2ValidationService;
@BeforeMethod(alwaysRun=true)
protected void setup()
{
// Get the object under test (here the determination engine)
level2ValidationService = (ValidationService) getAppContext().getBean("validationService");
// and replace the services as documented above.
MockitoAnnotations.initMocks(this);
ForeignAddress foreignAddress = new ForeignAddress();
foreignAddress.setCountryCode("7029");
foreignAddress.setForeignPostalCode("foreign");
// mock country to be able to return a fixed id
Country country = mock(Country.class);
foreignAddress.setLand(country);
doReturn(Integer.valueOf(1)).when(country).getId();
doReturn(country).when(countryService).getCountryById(anyInt());
ContextualAddressBean context = new ContextualAddressBean(foreignAddress, "", AddressContext.CORRESPONDENCE_ADDRESS);
postalCodeMinLength0.add(context);
}
@Test
public void PostalCodeMinLength0_ExpectError()
{
// Execute
level2ValidationService.validateFields(postalCodeMinLength0, null);
}
Qualsiasi idea di cosa fare se voglio mantenere questa annotazione @Transactional, ma anche essere in grado di stub i Méthodes countryservice?
saluti,
Michael
Potrebbe essere più preciso su come sai perché il mockito sta fallendo? Anche se non è correlato al problema, si dovrebbe notare che il valore di mocking non è veramente raccomandato, si dovrebbe invece creare un'istanza di valore da soli, magari con un factory personalizzato nel test o un costruttore privato, ecc ... – Brice
Inoltre si potrebbe mostra un po 'più di 'BaseTestDomainIntegration' e forse la spring config se è rilevante. – Brice
ciao, ho aggiunto più informazioni. vedere i proiettili – Michael