Задержка проверки EasyMock - PullRequest
       24

Задержка проверки EasyMock

3 голосов
/ 05 января 2010

Я использую EasyMock для создания фиктивных объектов для тестирования JUnit на Java. Я создаю фиктивный объект и передаю его другому потоку, где он ожидает вызова методов. В другом потоке вызовы заключены в блок try/catch(Throwable), поэтому, когда в макете происходит неожиданный вызов и, таким образом, выдается AssertionError, эта ошибка перехватывается блоком catch и обрабатывается. Таким образом, даже если произошел неожиданный вызов, тест проходит успешно.

Чтобы тест не удался, как и ожидалось, я бы хотел отложить всю проверку вызовов на вызов EasyMock.verify(mock), сделанный в потоке организатора теста в конце. Это возможно и как?

Ответы [ 4 ]

1 голос
/ 05 января 2010

Я не уверен, как это сделать с EasyMock, но такое поведение возможно с Mockito , потому что утверждения проверки могут быть указаны в конце теста.

1 голос
/ 05 января 2010

Правильное решение, которое я предполагаю, - перестать ловить Throwable. Это поймает все Error s, как вы находите, что может быть довольно опасно ... вы абсолютно уверены, что вам нужно на 100% поймать Throwable? Почему?

(Если окажется, что вы это сделаете, вы можете специально поймать AssertionError и отбросить его. Но это ужасно!)

0 голосов
/ 30 июня 2012

Как подсказал @deterb, это возможно с Mockito, но вы должны знать имя метода или устанавливать ожидания для каждого метода. Вот пример:

Перемешиваемый интерфейс:

public interface MyInterface {

    void allowedMethod();

    void disallowedMethod();
}

Пользовательский класс, который ловит AssertionError:

public class UserClass {

    public UserClass() {
    }

    public static void throwableCatcher(final MyInterface myInterface) {
        try {
            myInterface.allowedMethod();
            myInterface.disallowedMethod();
        } catch (final Throwable t) {
            System.out.println("Catched throwable: " + t.getMessage());
        }
    }
}

И тест Мокито:

@Test
public void testMockito() throws Exception {
    final MyInterface myInterface = mock(MyInterface.class);

    UserClass.throwableCatcher(myInterface);

    verify(myInterface, never()).disallowedMethod(); // fails here
}

То же самое возможно с EasyMock, но требуется некоторая работа:

@Test
public void testEasyMock() throws Exception {
    final AtomicBoolean called = new AtomicBoolean();
    final MyInterface myInterface = createMock(MyInterface.class);
    myInterface.allowedMethod();

    myInterface.disallowedMethod();
    final IAnswer<? extends Object> answer = new IAnswer<Object>() {

        @Override
        public Object answer() throws Throwable {
            System.out.println("answer");
            called.set(true);
            throw new AssertionError("should not call");
        }

    };
    expectLastCall().andAnswer(answer).anyTimes();

    replay(myInterface);

    UserClass.throwableCatcher(myInterface);

    verify(myInterface);
    assertFalse("called", called.get()); // fails here
}

К сожалению, вы также должны знать имена методов здесь, и вы должны определить ожидания как myInterface.disallowedMethod() и expectLastCall().andAnswer(answer).anyTimes().

Другая возможность - создать прокси с классом Proxy (с пользовательским InvocationHandler) и использовать его в качестве фиктивного объекта. Это определенно требует больше работы, но это может быть самое настраиваемое решение.

Наконец, не забывайте, что также возможно создать пользовательскую реализацию с делегированием или без делегирования объекту-модели EasyMock. Вот один с делегацией:

public class MockedMyInterface implements MyInterface {

    private final MyInterface delegate;

    private final AtomicBoolean called = new AtomicBoolean();

    public MockedMyInterface(final MyInterface delegate) {
        this.delegate = delegate;
    }

    @Override
    public void allowedMethod() {
        delegate.allowedMethod();
    }

    @Override
    public void disallowedMethod() {
        called.set(true);
        throw new AssertionError("should not call");
    }

    public boolean isCalled() {
        return called.get();
    }

}

И тест для него:

@Test
public void testEasyMockWithCustomClass() throws Exception {
    final MyInterface myInterface = createMock(MyInterface.class);
    myInterface.allowedMethod();

    final MockedMyInterface mockedMyInterface = 
        new MockedMyInterface(myInterface);

    replay(myInterface);

    UserClass.throwableCatcher(mockedMyInterface);

    verify(myInterface);
    assertFalse("called", mockedMyInterface.isCalled()); // fails here
}
0 голосов
/ 05 января 2010

Попробуйте использовать хорошие макеты:

http://easymock.org/EasyMock2_5_2_Documentation.html

"Ницца издевается В объекте Mock, возвращаемом методом createMock (), поведение по умолчанию для всех методов заключается в создании ошибки AssertionError для всех непредвиденных вызовов методов. Если вам нужен «красивый» Mock Object, который по умолчанию разрешает все вызовы методов и возвращает соответствующие пустые значения (0, null или false), используйте взамен createNiceMock (). «

Значения по умолчанию будут возвращаться для непредвиденных вызовов вместо того, чтобы выдавать AssertionError, но вы все равно можете проверить их с помощью метода verify () (в этом случае будут выданы AssertionErrors)

...