2010-11-15 10 views
19

Załóżmy fragment kodu testowego:Czy istnieje sposób na coś takiego, jak argument JUnit Assert w metodzie weryfikacji Mockito?

Observable model = Class.forName(fullyQualifiedMethodName).newInstance(); 
Observer view = Mockito.mock(Observer.class); 
model.addObserver(view); 
for (Method method : Class.forName(fullyQualifiedMethodName).getDeclaredMethods()) 
{ 
    method.invoke(model, composeParams(method)); 
    model.notifyObservers(); 
    Mockito.verify(
    view, Mockito.atLeastOnce() 
).update(Mockito.<Observable>any(), Mockito.<Object>any()); 
} 

Mockito.verify metoda zgłasza wyjątek, jeśli metoda w modelu nie został wywołany Observable.setChanged() metody.

Problem: bez dodawania loggers/System.print.out Nie mogę stwierdzić, jaka jest aktualna metoda, która nie powiodła się. Czy istnieje sposób, że coś podobnego do jUnit Assert metod:

Assert.assertEquals(
    String.format("instances %s, %s should be equal", inst1, inst2), 
    inst1.getParam(), 
    inst2.getParam() 
); 

ROZWIĄZANIE:

verify(observer, new VerificationMode() 
{ 
    @Override 
    public void verify(VerificationData data) 
    { 
    assertTrue(
     format(
      "method %s doesn't call Observable#setChanged() after changing the state of the model", 
      method.toString() 
     ), 
     data.getAllInvocations().size() > 0); 
    } 
}).update(Mockito.<Observable>any(), Mockito.<Object>any()); 

Odpowiedz

17

To załatwia sprawę (proste i jasne):

try { 
verify(myMockedObject, times(1)).doSomthing(); 
} catch (MockitoAssertionError e) { 
    throw new MockitoAssertionError("Was expecting a call to myMockedObject.doSomthing but got "+ e.getMessage()); 
} 
+6

Przekazywanie przyczyny jako drugiego argumentu jest zwykle lepsze niż łączenie wiadomości. 'throw new MockitoAssertionError (" message ", e)' – Kapep

+1

MockitoAssertionError nie ma konstruktora z parametrami MockitoAssertionError (String, Exception) Używam 'new AssertionError (" message ", exception)', ponieważ jest to typ wyjątku jest wyrzucane przez JUnit dla stwierdzeń. –

3

Nie ma bezpośredniego połączenia API, które pozwala na sprawdzenie wiadomości. Ale myślę, że jeśli zmienisz swój podpis weryfikacyjny, aby użyć obiektu metody zamiast Mockito.any(), to toString() na klasie Method wkroczy i da ci to, co chcesz.

Coś takiego.

import static org.mockito.Matchers.anyObject; 
import static org.mockito.Mockito.atLeastOnce; 
import static org.mockito.Mockito.verify; 
import static org.mockito.Matchers.eq; 

... 

Observable model = Class.forName("class name").newInstance(); 

verify(view, times(1)).update(eq(model), anyObject()); 

for (Method method : Class.forName("class name").getDeclaredMethods()) 
{ 
    method.invoke(model, composeParams(method)); 
    model.notifyObservers(); 
    verify(view, atLeastOnce()).update(eq(method), anyObject()); 
} 
+0

Niezła próba, ale to nie będzie działać. Pierwsza metoda aktualizacji Observer # (Źródło obiektu, Object arg) to model, który nadaje zmianę, a nie metoda, która zmieniła swój stan. –

+0

Po prostu dodaj oczekiwanie, które chcesz zobaczyć. Jeśli obejmuje to inny typ obserwowalnego, to niech tak będzie. –

+0

Prawdopodobnie musisz dodać więcej kodu, który lepiej wyjaśni Twoją strukturę klas. –

1

Można utworzyć matcher, aby wydrukować informacje o bieżącej metodzie. To będzie trochę niezgrabne, ale zadziała, wydrukuj nazwę metody, gdy weryfikacja się nie powiedzie.

6

Nie można wykonywać w trybie mockito. Składnia Mockito bardzo ułatwia przetestowanie oczekiwanego zachowania, ale nie ma koncepcji stanu testowego.

To, co próbujesz zrobić, to mieć pewne informacje, które nie znajdują się w szyderczym obiekcie, gdy fałszywe oczekiwania nie spełniają oczekiwań.

Jeśli naprawdę chcesz to zrobić, widzę 2 Ogólne sposoby: albo utworzyć własną verificationMode wdrożenie interfejsu

org.mockito.verification; 
public static interface VerificationMode 

i dodanie metody takie jak atLeastOnceMsd (MSG String), który pojawi się komunikat w przypadku niepowodzenia lub dodania aktualnej testowanej metody w modelu do obiektu widoku

na przykład z podobną linią w wewnętrznej pętli.

view.setName("now we are testing " + method.getName()); 
Powiązane problemy