Mockito - фиктивная базовая реализация при тестировании реализации производного класса того же метода

Я использую Mockito для модульного тестирования. У меня есть следующие классы:

public class Base {
    public void say() {
        System.out.println("Base"); // some work in the base class
    }
}

public class Derived extends Base {
    @Override
    public void say() {
        super.say();   // do the base class work
        System.out.println("Derived"); // some additional work in the derived class
    }
}

Теперь я хочу протестировать метод say() класса Derived, издеваясь над базовым методом say(). Я последовал предложению здесь: Mockito Как издеваться только над вызовом метода суперкласса и теперь у меня есть.

public class DerivedTest {
    @Test
    public void testSay() {
        Derived obj = Mockito.spy(new Derived());
        Mockito.doNothing().when((Base)obj).say();
        obj.say();
        // assert only "Derived" was output
    }
}

Но это не работает, так как имитирует как базовую, так и производную реализацию класса. Я хочу проверить только дополнительную логику в производном классе.

Как я могу это сделать.

Обновление: мое решение

Поскольку я не мог изменить базовый класс, как было предложено, я изменил свой производный класс, чтобы извлечь всю дополнительную логику в отдельный метод, и просто протестировал этот метод.

public class Derived extends Base {
    @Override
    public void say() {
        super.say();   // do the base class work
        doAdditionalWork();  // some additional work in the derived class
    }

    void doAdditionalWork() {
        System.out.println("Derived");
    }
}

public class DerivedTest {
    @Test
    public void testDoAdditionalWork() {
        Derived obj = new Derived();
        obj.doAdditionalWork();
        // assert only "Derived" was output
    }
}

Это означает, что я все еще не тестирую производный метод say(), но, учитывая, что логика там довольно проста, я надеюсь, что меня можно за это извинить. Другим недостатком является то, что я не могу иметь более строгую видимость, чем пакет-частный для метода doAdditionalWork().


person Vivek    schedule 21.04.2014    source источник


Ответы (1)


Когда вы spy создаете объект, вы полностью заменяете реализацию метода (методов), для которого вы определили фиктивное поведение. Итак, как вы отметили в вопросе, это не сработает.

Один из трюков заключается в том, чтобы извлечь метод additionalBehavior() и протестировать только его, без шпионажа или насмешек:

public class Base {
    public void say() {
        System.out.println("Base"); // some work in the base class
        additionalBehavior();
    }

    protected void additionalBehavior() {
        // No implementation. Alternatively - make it abstract
    }
}

public class Derived extends Base {
    @Override
    protected void additionalBehavior() {
        System.out.println("Derived"); // some additional work in the derived class
    }
}

public class DerivedTest {
    @Test
    public void testAdditionalBehavior() {
        Derived obj = new Derived();
        obj.additioanlBehavior();
        // assert that "Derived" was the output
    }
}
person Mureinik    schedule 21.04.2014
comment
Спасибо за ответ. Однако я действительно не могу изменить базовый класс здесь. - person Vivek; 21.04.2014
comment
Вот в чем проблема. Вы можете только издеваться над слабыми связями; наследование, по определению, представляет собой тесную связь между типами. Вам обязательно нужно наследовать от Base или есть общий интерфейс, который может реализовать Derived? Если есть, вы можете использовать шаблон Decorator для достижения необходимой слабой связи. - person Lilshieste; 21.04.2014