Mam plik reguł drools, który używa klas usług w regułach. Więc jedna reguła robi coś takiego:Adnotacja transakcyjna pozwala uniknąć drwiania usług
eval (countryService.getCountryById (1)! = Null)
W validationservice że jest opatrzone @service i @Transactional (propagacja = Propagation.SUPPORTS) plik Drools jest wykorzystywany w bazie bezpaństwowej wiedzy i dodawane są fakty, które powinny być używane w ślinotokach. Po wykonaniu tej czynności wywoływana jest sesja.execute (fakty) i uruchamia się silnik reguł.
Aby przetestować reguły, chciałbym dodać nazwę countryService.getCountryById(). Nie ma większego problemu z używaniem mockito. Zrobiłem to dla innych usług, które używają również konfiguracji drools i działało dobrze. Jednak w tym konkretnym przypadku usługa countryService nie została przygnieciona i nie mogłem ustalić, dlaczego tak się dzieje. Po spędzeniu dużej ilości czasu i sprawdzeniu mojego kodu stwierdziłem, że posiadanie @Transactional powyżej usługi lub brak tej adnotacji zrobiło różnicę. Brak efektu @Transaction spowodował, że mockito kpi z usługi country bez problemu, dzięki temu, że @transactional na miejscu spowodowało, że mockito nie zdał (bez żadnego błędu lub podpowiedzi) wstrzyknięcia próbnego, więc użyto oryginalnego obiektu countryservice.
Moje pytanie brzmi, dlaczego ta adnotacja powoduje ten problem. Dlaczego nie można wstrzyknąć mockito podczas ustawiania @Transactional? Zauważyłem, że Mockito zawodzi jako kiedy debugowania i sprawdzić countryService gdy jest on dodawany jako globalny sesją ślini widzę następującą różnicę kiedy skontrolować countryservice w moim debugwindow:
z @ transakcyjny: countryService ma wartość CountryService $$ EnhancerByCGLIB $$ b80dbb7b
bez @transactional: countryService ma CountryService wartość $$ EnhancerByMockitoWithCGLIB $$ 27f34dc1
Ponadto z @t ransactional mój breakpoint w metodzie countryservice getCountryById zostaje znaleziony i debugger zatrzymuje się w tym punkcie przerwania, ale bez @transactional mój punkt przerwania jest pomijany, ponieważ mockito pomija go.
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);
}
I klasa 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);
}
Każdy pomysł, co zrobić, jeśli chcę utrzymać ten @transactional adnotacji ale także móc skrótową z methodes countryservice?
pozdrowienia,
Michael
Mógłbyś być bardziej precyzyjne, skąd wiesz, dlaczego mockito nie działa? Również niezwiązany z tą kwestią, należy pamiętać, że wartość kpiąca nie jest naprawdę zalecana, powinieneś zamiast tego sam stworzyć instancję wartości, może z niestandardową fabryką w swoim teście lub prywatnym konstruktorem, itd ... – Brice
Czy mógłbyś pokaż trochę więcej 'BaseTestDomainIntegration' i może config wiosną, jeśli jest to istotne. – Brice
Witam brice, dodałem więcej informacji. zobacz pociski – Michael