Archive for the ‘mockito’ Category

Ostatnio zdażyło mi się trafić na dosyć intrygujący problem: testy junitowe odpalane były poprzez runner’a spring’owego co umożliwiało wstrzykiwanie zależności poprzez config testowy. No ale to wszyscy znamy – problem pojawił w momencie gdy chciałem dodać runner’a mockito’wego gdyż adnotacja @RunWith nie oferuje takiej możliwości, no i już byłem przekonany, że trzeba będzie zakasać rękawy i napisać jakieś api np. z użyciem dekoratora, ale jak zwykle wyszedł ze mnie leń i postanowiłem sprawdzić czy ktoś już tego czasem nie zrobił.

Okazało się, że nie, ale ze względu na to, że @RunWith została dodana nieco późno i nie była do końca przemyślana. W junit’cie 4.7 wprowadzono tzw. Intereceptors ale zmieniono ich nazwę wraz z  wersją 4.8 na Rule.

Co daje nam ta adnotacja – możemy ją zaaplikować do publicznej własności naszego testu, i musi on implementować interfejs MethodRule. Reszta to już bułeczka z masełkiem – MethodRule zwraca Statement‚a, który w działaniu przypomina nieco advice’a Around, znanego użytkownikom AOP – zawijamy sobie statement, wywołujemy co nam trzeba, następnie execute na oryginale i już. Dla przykładu stwórzmy taka klase, która pozwoli nam tworzyć mocki, mockitowe z wykorzystaniem adnotacji @Mock.

package pl.bedkowski.code.rules;

import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.mockito.MockitoAnnotations;

public class InitMocks implements MethodRule {

	public Statement apply(final Statement stmt, FrameworkMethod arg1, final Object arg2) {
		return new Statement(){
			@Override
			public void evaluate() throws Throwable {
				MockitoAnnotations.initMocks(arg2);
				stmt.evaluate();
			}};
	}

}

No i jakis przykladowy tescik:

package pl.bedkowski.code.rules;

import static org.mockito.Mockito.when;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.mockito.Mock;

interface SomeInterface{
	String doSmth();
}

public class SampleTest {

	@Rule
	public MethodRule i = new InitMocks();

	@Mock
	private SomeInterface my;

	@Test
	public void testing() throws Exception {
		when(my.doSmth()).thenReturn("33");
	}
}

Ostatnio dotarłem do biblioteki mockito umożliwiającej tworzenie obiektów mock’owych w bardzo prosty sposów, mockowac można zarówno dla samych interfejsów jak i klas ostatecznych.

No to popatrzmy na przykładowy test:

@Test
public void test() throws Exception {
   Item item = new Item() {
      public String getName() {
           return "My name is...";
      }
   }
}

W tym prostym przypadku niby nei ma różnicy

a przy wykorzystaniu mockito:

@Test
public void test() throws Exception {
   Item item = mock(Item.class);
   when(item.getName()).thenReturn("Slim shady");
}

No niby nie ma różnicy, ale wyobraźmy sobie, ze interfejs ma 10 metod z których potrzbujemy do naszego przypadku testowego jedynie getName i jakie ono będzie nie ma większego znaczenia, ważne żeby zwracało to co chcemy.

Idzmy krok dalej – w projekcie nad którym obecnie pracuje cała masa rzeczy przechowywana jest w plikach xml, więc powiedzmy że dla każdego przypadku testowego trzeba edytować 3 pliki xml, po utowrzeniu odpowiedniej ilości testcase’ow nikomu nie chce się dodawać kolejnego i przedzierać przez gąszcz plików, z których część już dawno jest zdezaktualizowana.

No przykład jest prosty, ale taki też był zamysł tego wpisu – jako wstęp do analizy konkretnego przypadku i podzielenie sie paroma uwagami.