Могу ли я высмеивать вызов метода суперкласса?

Иногда вы хотите протестировать метод класса и хотите выполнить ожидание при вызове метода суперкласса. Я не нашел способ сделать это ожидание в java, используя easymock или jmock (и я думаю, что это невозможно).

Существует (относительное) чистое решение, чтобы создать делегат с логикой метода суперкласса, а затем установить на него ожидания, но я не знаю, почему и когда использовать это решение - любые идеи/примеры?

Спасибо

Ответы

Ответ 1

Хорошо, вы можете, если хотите. Я не знаю, знакомы ли вы с JMockit, идите проверить это. Текущая версия - 0.999.17. Пока что взглянем на нее...

Предположим, что следующая иерархия классов:

public class Bar {
    public void bar() {
        System.out.println("Bar#bar()");
    }
}

public class Foo extends Bar {
    public void bar() {
        super.bar();
        System.out.println("Foo#bar()");
    }
}

Затем, используя JMockit в FooTest.java, вы можете подтвердить, что вы действительно делаете вызов Bar из Foo.

@MockClass(realClass = Bar.class)
public static class MockBar {
    private boolean barCalled = false;

    @Mock
    public void bar() {
        this.barCalled = true;
        System.out.println("mocked bar");
    }
}

@Test
public void barShouldCallSuperBar() {
    MockBar mockBar = new MockBar();
    Mockit.setUpMock(Bar.class, mockBar);

    Foo foo = new Foo();
    foo.bar();

    Assert.assertTrue(mockBar.barCalled);

    Mockit.tearDownMocks();
}

Ответ 2

Я не думаю, что высмеиваю супер-вызов - мне кажется, что поведение есть часть поведения самого класса, а не поведение зависимости. Мышление всегда кажется, что это должно быть связано с зависимостями больше, чем что-либо еще.

Есть ли у вас хороший пример того типа звонка, который вы хотите издеваться? Если вы хотите издеваться над таким вызовом, стоит ли рассматривать композицию вместо наследования?

Ответ 3

Развернувшись на @Cem Catikkas, ответьте, используя JMockit 1.22:

@Test
public void barShouldCallSuperBar() {
    new MockUp<Bar>() {
        @Mock
        public void bar() {
            barCalled = true;
            System.out.println("mocked bar");
        }
    };

    Foo foo = new Foo();
    foo.bar();

    Assert.assertTrue(mockBar.barCalled);
}

Не требуется статический класс, аннотированный с помощью @MockClass, он заменяется классом MockUp.

Ответ 4

Нет, нет способа издеваться над методами суперкласса с jMock.

Однако существует и быстрое и грязное решение вашей проблемы. Предположим, что у вас есть класс A, а класс B расширяет A. Вы хотите издеваться над методом Aa() на B. Вы можете ввести класс C extends B в свой тестовый код и переопределить метод Ca() (просто вызвать super или вернуть null, id не важно). После этого издевайтесь над C и используйте макет везде, где вы будете использовать B.

Ответ 5

Есть несколько тестов, которые делают именно это (т.е. определяют ожидаемый вызов метода суперкласса) с использованием API ожиданий JMockit, в тестовом наборе анимированных переходов. Например, FadeInTest тестовый пример.

Ответ 6

перехват супервызов слишком мелкозернистый. Не переусердствуйте.