Шість простих прикладів по Mockito (переклад)

Маленький коментар:/*
Вирішив ознайомитися з тим, що з себе представляє ця бібліотека, і відшукав чудову статті, прочитання якої я хотів би закріпити, для чого і вирішив перекласти її на російську.
Звичайно ж, приймається конструктивна критика.
Сподіваюся, що коментарі будуть корисніше самої статті, як це зазвичай і буває. ;)
*/
Mockito — прекрасна мок-бібліотека для Java. Я зачарований тим, як легко використовувати в порівнянні з іншими подібними бібліотеками світу Java і .NET. У цій статті я наводжу все, що Вам потрібно для старту, у шести дуже легких прикладах.

Для початку скачайте mockito http://mockito.org/ (на момент написання веде на https://code.google.com/p/mockito/).
Або просто додайте в залежності в pom maven-проекту:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<!-- на момент написання версія була 1.10.10 -->

Майже все найцікавіше може бути взяте із класу org.mockito.Mockito (або статично імпортувати його методи, що я і використовую в цій статті). Отже, почнемо.

Щоб створити заглушку (або мок), використовуйте mock(class). Потім використовуйте when(mock).thenReturn(value), щоб вказати значення, що повертається, для методу. Якщо Ви вкажете більше одного значення, що повертається, вони будуть повернуті методом послідовно, поки не повернеться останнім, після цього при наступних викликах буде повертатися тільки останнє значення (таким чином, щоб метод завжди повертав одне і те ж значення, просто вкажіть його один раз). Наприклад:
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import java.util.Iterator;
import org.junit.Test;
....
@Test
public void iterator_will_return_hello_world() {
//підготовляємо
Iterator i = mock(Iterator.class);
when(i.next()).thenReturn("Привіт").thenReturn("World");
//виконуємо
String result = i.next()+" "+i.next();
//порівнюємо
assertEquals("Hello World", result);
}

Цей приклад демонструє створення мок-ітератора і «змушує» його повертати «Hello» при першому виклику методу next(). Наступні виклики цього методу будуть повертати «World». Після цього ми можемо виконувати звичайні assert'и.
Заглушки також можуть повертати різні значення в залежності від передаються у метод аргументів. Приклад:
@Test
public void with_arguments() {
Comparable c = mock(Comparable.class);
when(c.compareTo("Test")).thenReturn(1);
assertEquals(1, c.compareTo("Test"));
}

Тут ми створюємо об'єкт-заглушку Comparable, і повертаємо 1 у разі, якщо він порівнюється з певним String-значенням («Test», в даному випадку).
Якщо метод має якісь аргументи, але Вам все одно, що буде в них передано або передбачити це неможливо, то використовуйте anyInt() (і альтернативні значення для інших типів). Приклад:
@Test
public void with_unspecified_arguments() {
Comparable c = mock(Comparable.class);
when(c.compareTo(anyInt())).thenReturn(-1);
assertEquals(-1, c.compareTo(5));
}

Ця заглушка повертає -1 незалежно від переданого аргументу. Void-методи становлять деяку проблему, так як Ви не можете використовувати їх в методі when().
Альтернативним синтаксисом в цій ситуації буде doReturn(result).when(mock_object).void_method_call();. Замість повернення результату Ви також можете використовувати .thenThrow() або doThrow() void-методів. Приклад:
@Test(expected=IOException.class)
public void OutputStreamWriter_rethrows_an_exception_from_outputstream() 
throws IOException {
OutputStream mock = mock(OutputStream.class);
OutputStreamWriter osw = new OutputStreamWriter(mock);
doThrow(new IOException()).when(mock).close();
osw.close();
}

У цьому прикладі викидається IOException, коли в заглушці OutputStream викликається метод close. Ми з легкістю перевіряємо, що OutputStreamWriter прокидає такий эксепшн назовні.
Щоб перевірити, що метод дійсно був викликаний (типове використання об'єктів-заглушок), ми можемо використовувати verify(mock_object).method_call;. Приклад:
@Test
public void OutputStreamWriter_Closes_Outputstream_on_close()
throws IOException {
OutputStream mock = mock(OutputStream.class);
OutputStreamWriter osw = new OutputStreamWriter(mock);
osw.close();
verify(mock).close();
}

У цьому прикладі ми перевіряємо, що OutputStreamWriter здійснює виклик методу close() у вкладеному OutputStream.
Ви можете використовувати аргументи в методах і підстановки для них, такі як anyInt(), як в одному з попередніх прикладів. Варто відзначити, що Ви не можете змішувати літерали і матчеры. Використовуйте матчер eq(value) для конвертування літерала в матчер, який порівняє значення. Mockito надає багато вже готових матчеров, але іноді Вам може знадобитися більш гнучкий підхід. Приміром, OutputStreamWriter буде буферизувати висновок і потім передавати його обернутому об'єкту при заповненні буфера, але ми не знаємо, наскільки довгий буфер нам збираються передати. Тут ми не можемо використовувати порівняння на рівність. Однак, ми можемо запив власний матчер:
@Test
public void OutputStreamWriter_Buffers_And_Forwards_to_outputstream() 
throws IOException { 
OutputStream mock = mock(OutputStream.class);
OutputStreamWriter osw = new OutputStreamWriter(mock);
osw.write('a');
osw.flush();
// не можемо робити так, тому що ми не знаємо,
// наскільки довгим може бути масив
// verify(mock).write(new byte[]{'a'}, 0, 1);

BaseMatcher arrayStartingWithA = new BaseMatcher() {
@Override
public void describeTo(Description description) {
// порожнеча
}
// Перевіряємо, що перший символ - це A
@Override
public boolean matches(Object item) {
byte[] actual = (byte[]) item;
return actual[0] == 'a';
}
};
// перевіряємо, що перший символ масиву - це A, і що інші два аргументи дорівнюють 0 і 1.
verify(mock).write((byte[]) argThat(arrayStartingWithA), eq(0), eq(1)); 
}

І це все, що Вам потрібно, щоб почати. А зараз візьміть і отрефакторите всю цю изимокщину у своїх проектах!

Весь текст класу з тестами:
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Iterator;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Test;

public class MockitoTests {
@Test
public void iterator_will_return_hello_world() {
//підготовляємо
Iterator i = mock(Iterator.class);
when(i.next()).thenReturn("Привіт").thenReturn("World");
//виконуємо
String result = i.next() + " " + i.next();
//порівнюємо
assertEquals("Hello World", result);
}

@Test
public void with_arguments() {
Comparable c = mock(Comparable.class);
when(c.compareTo("Test")).thenReturn(1);
assertEquals(1, c.compareTo("Test"));
}

@Test
public void with_unspecified_arguments() {
Comparable c = mock(Comparable.class);
when(c.compareTo(anyInt())).thenReturn(-1);
assertEquals(-1, c.compareTo(5));
}

@Test(expected = IOException.class)
public void OutputStreamWriter_rethrows_an_exception_from_outputstream()
throws IOException {
OutputStream mock = mock(OutputStream.class);
OutputStreamWriter osw = new OutputStreamWriter(mock);
doThrow(new IOException()).when(mock).close();
osw.close();
}

@Test
public void OutputStreamWriter_Closes_Outputstream_on_close()
throws IOException {
OutputStream mock = mock(OutputStream.class);
OutputStreamWriter osw = new OutputStreamWriter(mock);
osw.close();
verify(mock).close();
}

@Test
public void OutputStreamWriter_Buffers_And_Forwards_to_outputstream()
throws IOException {
OutputStream mock = mock(OutputStream.class);
OutputStreamWriter osw = new OutputStreamWriter(mock);
osw.write('a');
osw.flush();
// не можемо робити так, тому що ми не знаємо,
// наскільки довгим може бути масив
// verify(mock).write(new byte[]{'a'},0,1);

BaseMatcher arrayStartingWithA = new BaseMatcher() {
@Override
public void describeTo(Description description) {
// порожнеча
}

// Перевіряємо, що перший символ - це A

@Override
public boolean matches(Object item) {
byte[] actual = (byte[]) item;
return actual[0] == 'a';
}
};
// перевіряємо, що перший символ масиву - це A, і що інші два аргументи дорівнюють 0 і 1.
verify(mock).write((byte[]) argThat(arrayStartingWithA), eq(0), eq(1));
}
}

P. S.: Далі можна почитати введення в PowerMock: http://habrahabr.ru/post/172239/.
І ось цю статтю: http://habrahabr.ru/post/72617/

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.