Some of posts from this blog has been moved to dywicki.pl. You will be automatically redirected to new blog if you would submit comment.
New posts are published on dywicki.pl, this blog contains old content and it is not continued.

Niektóre posty z tego bloga zostały przeniesione do dywicki.pl. Zostaniesz automatycznie przekierowany jeśli bedzięsz chciał dodać komentarz.
Nowe posty sa publikowane na dywicki.pl, ten blog zawiera stare treści i nie jest kontynuowany.

EasyMock i IAnswer, recepta na zachowanie metod

Filed under Java,Porady,Testy jednostkowe by

Złym zwyczajem jest modyfikowanie argumentów zamiast zwracania nowej wartości, jakkolwiek trafiają się sytuacje gdy testowany kod powinien weryfikować takie wywołania. W EasyMock mamy do dyspozycji w takim przypadku interfejs IAnswer. Jego użycie jest w miarę proste – dobieramy się do tablicy argumentów i robimy z nią co potrzeba.

Oto przykład – interfejs Populator dodaje do przekazanej tablicy określoną wartość w puste miejsca. Zwraca też ilość zmian, które zaprowadził. Całość jest oparta na bardzo prostym kodzie, zaledwie jedna pętla, jakkolwiek na potrzeby przykładu jest to wystarczające. Pragnę jednak nadmienić, że w podobny sposób można testować bardziej złożony kod, gdzie kolaborują ze sobą dwa obiekty – tj. Observator i Observable czy też Visitor i Visitable.

package org.code_house.test.mock;

interface Populator {
    int fill(String value, String[] arguments);
}

Implementacja interfejsu jest bardzo prosta:

package org.code_house.test.mock;

class FillAnswer implements IAnswer<Integer> {
    public Integer answer() throws Throwable {
        // pobranie argumentow
        Object[] arguments = EasyMock.getCurrentArguments();
        String name = (String) arguments[0];
        Object[] values = (Object[]) arguments[1];

        // logika potrzebna do testu
        int populated = 0;
        for (int i = 0; i < values.length; i++) {
            if (values[i] == null) {
                populated++;
                values[i] = name;
            }
        }
        return populated;
    }
}

Test jest również niezbyt skomplikowany – bazuje on na poprzedniej nocie – “Testowanie tablic argumentów z EasyMock”:

package org.code_house.test.mock;

import static org.easymock.EasyMock.*;
import org.easymock.IAnswer;

import java.util.Arrays;

import junit.framework.TestCase;

public class AnswerTest extends TestCase {

    public void testPopulate() {
        Populator populator = createMock(Populator.class);
        expect(populator.fill(eq("Code House"), aryEq(new String[3])))
            .andAnswer(new FillAnswer());
        expect(populator.fill(eq("Code House"), aryEq(new String[] {"1"})))
            .andAnswer(new FillAnswer());
        replay(populator);

        // tablica do wypełnienia
        String[] populated = new String[3];
        int added = populator.fill("Code House", populated);
        assertEquals(3, added);
        // w odpowiedzi oczekujemy dodania 3 nowych elementów
        assertTrue(Arrays.equals(
            new String[] {"Code House", "Code House", "Code House"},
            populated
        ));

        // w tym przypadku nie oczekujemy nowości
        added = populator.fill("Code House", new String[] {"1"});
        assertEquals(0, added);
    }
}

2 responses so far

2 Responses to “EasyMock i IAnswer, recepta na zachowanie metod”

  1. marek says:

    fajny trick :)

  2. milus says:

    Witam

    Całkiem fajnie. Nie wiedziałem/doczytałem, że w implementcaji IAnswer można dostać się do parametrów wywołania metody.
    Ja do takich celów korzystąłem z mechanizmu Capture dostępny w EasyMock.

Leave a Reply