JMockit: как переопределить уже издевавшийся метод новым издевательством?


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

У меня есть следующий (очень простой) класс:

public class Dummy {
    public void foo() {System.out.println("O");}
}
Теперь у меня есть следующие тесты, где в каждом из них я пытаюсь поиздеваться над методом "foo" несколько раз (каждый тест делает это немного по-другому):

Тест №1

@Test
public void test1() {

    new MockUp<Dummy>() {

        @Mock
        public void foo(Invocation inv) {

            System.out.println("A");
            inv.proceed();
        }
    }

    new MockUp<Dummy>() {

        @Mock
        public void foo(Invocation inv) {

            System.out.println("B");
            inv.proceed();
        }
    }

    new Dummy().foo();
}

Тест №2

@Test
public void test2() {

    mock("A");
    mock("B");
    new Dummy().foo();
}

private void mock(final String s) {

    new MockUp<Dummy>() {

        @Mock
        public void foo(Invocation inv) {

            System.out.println(s);
            inv.proceed();
        }
    }
}

Единственное различие между тестами заключается в извлечении макетного кода в другой метод. Но результаты не те же самые...

Тест №1 вывод:

B
A
B
O

Это странно, потому что я бы вообще не ожидал появления А. Но в любом случае, вот результат теста №2:

B
A
A
A
...ad infinitum

Тест №2 не пройдет с StackOverflowError.

Это ошибка или я что-то упустил?

Обновление (с решением)

Как уже упоминал @Rogério, такое поведение неприемлемо.
Тогда как же можно обойти МОК? любить это:
private MockUp<Dummy> mock;

@Test
public void test3() {

        mockCorrectly("A");
        mockCorrectly("B");
        new Dummy().foo();
}


private void mockCorrectly(final String s) {

    if (mock != null) {
        mock.tearDown();
    }

    mock = new MockUp<Dummy> {

        @Mock
        public void foo(Invocation inv) {

            System.out.println(s);
            inv.proceed();
        }
    }
}

И для вывода:

B
O

Отлично :)

1 3

1 ответ:

Неясно, что именно здесь происходит; по-видимому, во время выполнения происходит какое-то "цепное издевательство".

Реальная проблема заключается в том, что оба теста делают что-то недопустимое с API MockUp: они издеваются над тем же самым методом в одном и том же классе дважды в одном и том же тесте. Это нормально иметь два разных макета для одного и того же класса в одном и том же тесте, пока они имитируют различные методы/конструкторы.

Результирующее поведение не определено, так как JMockit этого не делает. поддержка нескольких одновременных издевательств над одним и тем же методом.