2012-08-03 20 views
39

Używam Mockito 1.9.0. W jaki sposób sprawdzić, czy metoda została wywołana dokładnie jeden raz i że jedno z pól przekazanych do niej zawiera pewną wartość? W moim teście JUnit, mamKorzystając z Mockito, jak sprawdzić, czy metoda została wywołana z określonym argumentem?

@Before 
public void setupMainProg() { 
    // Initialize m_orderSvc, m_opportunitySvc, m_myprojectOrgSvc 
    ... 
    m_prog = new ProcessOrdersWorker(m_orderSvc, m_opportunitySvc, m_myprojectOrgSvc); 
} // setupMainProg 

@Test 
public void testItAll() throws GeneralSecurityException, IOException { 
    m_prog.work(); 
} 

z „praca” metoda wywołuje metodę „m_orderSvc” (jeden z argumentów przekazanych do obiektu). "m_orderSvc" z kolei zawiera pole członka, "m_contractsDao". Chcę sprawdzić, czy "m_contractsDao.save" zostało wywołane dokładnie raz i że przekazywany do niego argument zawiera pewną wartość.

Może to być trochę mylące. Daj mi znać, jak mogę wyjaśnić moje pytanie i cieszę się, że mogę to zrobić.

Odpowiedz

48

Najpierw musisz utworzyć symulację m_contractsDao i skonfigurować. Zakładając, że klasa to ContractsDao:

ContractsDao mock_contractsDao = mock(ContractsDao.class); 
when(mock_contractsDao.save(any(String.class))).thenReturn("Some result"); 

Następnie wstrzyknij próbkę do m_orderSvc i wywołaj metodę.

m_orderSvc.m_contractsDao = mock_contractsDao; 
m_prog = new ProcessOrdersWorker(m_orderSvc, m_opportunitySvc, m_myprojectOrgSvc); 
m_prog.work(); 

Wreszcie, należy sprawdzić, czy makiety nazwano odpowiednio:

verify(mock_contractsDao, times(1)).save("Parameter I'm expecting"); 
+9

FYI, można pozostawić wyłączony 'czasy (1)', jak to jest zawsze domniemanych chyba dodać kwantyfikator określający coś innego niż dokładnie jednym czasie. I zamiast 'any (String.class)' istnieje nieco bardziej wygodny 'anyString()'. –

+3

Warto również zauważyć, że argument, który został przekazany do metody PO "weryfikuj" jest porównywany z użyciem 'equals' do argumentu, który został przekazany podczas rzeczywistego testu. Tak więc, niezależnie od metody (metoda 'save' w przykładzie mamboking), pomyśl o _type_ każdego parametru io tym, czy faktycznie potrzebujesz porównania z' equals'. Jeśli chcesz przetestować argument za pomocą czegoś innego niż 'równy ', potrzebujesz' ArgumentMatcher' jakiegoś rodzaju (który może być 'ArgumentCaptor' jak w odpowiedzi Kevina Welkera). –

+0

Jak określić dokładnie raz, nie dwa lub więcej? Komentarz @ KevinWelker mówi, że jest ukryty, ale nie jest pewny, czy oznacza dokładnie jeden raz, czy chociaż raz. – aliteralmind

21

Building off odpowiedzi Mamboking za:

ContractsDao mock_contractsDao = mock(ContractsDao.class); 
when(mock_contractsDao.save(anyString())).thenReturn("Some result"); 

m_orderSvc.m_contractsDao = mock_contractsDao; 
m_prog = new ProcessOrdersWorker(m_orderSvc, m_opportunitySvc, m_myprojectOrgSvc); 
m_prog.work(); 

Adresowanie prośbę o sprawdzenie, czy argument zawiera pewna wartość, mógłbym założyć, że masz na myśli, że argument jest ciągiem i chcesz sprawdzić, czy argument String zawiera podłańcuch. Do tego można zrobić:

ArgumentCaptor<String> savedCaptor = ArgumentCaptor.forClass(String.class); 
verify(mock_contractsDao).save(savedCaptor.capture()); 
assertTrue(savedCaptor.getValue().contains("substring I want to find"); 

Jeśli to założenie było błędne, a argument save() jest zbiorem pewnego rodzaju, byłoby tylko nieznacznie różni:

ArgumentCaptor<Collection<MyType>> savedCaptor = ArgumentCaptor.forClass(Collection.class); 
verify(mock_contractsDao).save(savedCaptor.capture()); 
assertTrue(savedCaptor.getValue().contains(someMyTypeElementToFindInCollection); 

Można również sprawdzić w ArgumentMatchers, jeśli wiesz, jak używać dopasowań Hamcrest.

7

Jest to lepsze rozwiązanie:

verify(mock_contractsDao, times(1)).save(Mockito.eq("Parameter I'm expecting")); 
+0

To jest lepsze kiedy masz do czynienia z typami nie pierwotnymi. – pisaruk

Powiązane problemy