JMockit MockUp сохраняется между тестами Spock

Я использую тест Spock, написанный на Groovy, чтобы проверить некоторый Java-код. Я использую JMockit для имитации методов в java-коде, поскольку Спок обрабатывает только имитирующие классы Groovy. Я столкнулся с проблемой, когда JMockit MockUp сохраняется между тестами. Такой макет должен существовать только для теста (согласно документации JMockit), но это не работает, и я полагаю, это потому, что он не использует средство запуска тестов JMockit, а скорее средство запуска тестов Spock.

Вот простейший пример проблемы, с которой я столкнулся. У меня есть простой метод, возвращающий строку, я могу изменить возвращаемое значение метода с помощью MockUp, но он все еще существует для третьего теста, который не ожидает его использования.

Класс Java

public class ClassToTest {
    public String method() {
        return "original";
    }
}

Тест Спока

class ClassToTestSpec extends Specification {
    void "first test"() {
        when:
        String result = new ClassToTest().method()

        then:
        result == "original"
    }

    void "second test"() {
        setup:
        new MockUp<ClassToTest>() {
            @Mock
            public String method() {
                return "mocked"
            }
        }

        when:
        String result = new ClassToTest().method()

        then:
        result == "mocked"
    }

    void "third test"() {
        when:
        String result = new ClassToTest().method()

        then:
        result == "original"
    }
}

Третий тест не проходит, потому что ClassToTest.method() по-прежнему возвращает строку «mocked», а не «original». С помощью отладчика я подтвердил, что метод Mocked вызывается дважды.

Вопрос

Есть ли способ вручную удалить класс MockUp в JMockit? Спасибо.


person mnd    schedule 31.12.2014    source источник
comment
Спок может издеваться над классами Java и Groovy. Издевательство над тестируемым классом - это запах, и его следует использовать с осторожностью.   -  person Peter Niederwieser    schedule 31.12.2014
comment
Спасибо за ответ @PeterNiederwieser, я не могу использовать обычную нотацию, instance.method() >> result, вы можете указать мне правильное направление?   -  person mnd    schedule 31.12.2014
comment
Сотрите это, нотация работает, я забыл создать экземпляр объекта с помощью Mock, например ClassToTest instance = Mock(ClassToTest). Теперь выясним, как сделать это частичной имитацией, возможно, с помощью шпиона.   -  person mnd    schedule 31.12.2014
comment
Если вам абсолютно нужен / нужен полумок, Spy() - это то, что вам нужно. Часто лучше провести рефакторинг тестируемого кода или пересмотреть, что и как тестировать.   -  person Peter Niederwieser    schedule 31.12.2014


Ответы (2)


Вы можете вызвать метод MockUp.tearDown для созданного объекта мокапа, чтобы вручную отменить его эффекты.

person Rogério    schedule 01.01.2015
comment
Чудесно! Спасибо @Rogerio! - person mnd; 05.01.2015
comment
Лично мне не повезло с методом tearDown в тесте spock. Если у кого-то это работает, я хотел бы увидеть пример Спецификации. Спасибо. На данный момент я избегаю Jmockit in spock. - person keaplogik; 10.02.2015
comment
Начиная с JMockit 1.28 этот ответ больше недействителен, поскольку MockUp#tearDown был удален. - person Vampire; 05.09.2019

Не совсем ответ на вопрос - потому что я до сих пор не знаю, можно ли вручную удалить MockUp JMockit. Но благодаря комментариям @ PeterNiederwieser я обнаружил, что вы действительно можете создать частичный макет для класса Java. Ниже показано изменение второго теста сверху.

void "second test"() {
    setup:
    ClassToTest test = Spy(ClassToTest) {
        method() >> "mocked"
    }

    when:
    String result = test.method()

    then:
    result == "mocked"
}

Питер упомянул о пересмотре того, как и что тестировать, если Spy() необходим, но для моего случая использования это предпочтительнее.

person mnd    schedule 31.12.2014