Проверка вызова защищенного супер метода
У меня есть следующая структура:
class Bar{
....
protected void restore(){
....
}
....
}
Этот класс расширяется на Foo
, как показано ниже:
class Foo extends Bar{
....
@Override
public void restore(){ //valid override
super.restore();
....
}
}
В моем тесте jUnit я хотел бы проверить, что когда foo.restore()
вызывается, то super.restore()
вызывается впоследствии. Следовательно, ниже приведен мой метод теста jUnit:
class FooTest{
@Tested
Foo _foo;
@Test
void testRestore(final Bar bar){
new Expectations(){{
bar.restore(); times = 1; // Error! bar.restore() not visible
}};
Deencapsulation.invoke(_foo,"restore");
}
}
К сожалению, мой тест не может компилироваться. Причина в том, что 1) restore()
родителя является protected
и 2) FooTest
и Foo
существуют вместе в отдельном проекте (и, следовательно, папке) против Bar
.
Есть ли вообще чтобы добиться желаемого теста? Я проверил jmockit tutorials (много раз за последние несколько месяцев) и не видел подобного теста (то же самое касается поиска в Google).
Обновить
С помощью ответов я понимаю, что принуждение подклассов к вызову super
не является лучшей практикой, но это не моя реализация, и я все еще должен проверить ее. Я все еще ищу способ применить мой тест jUnit, чтобы проверить, если вызов к родителю происходит.
3 ответа:
Должен сработать следующий тест:
public class FooTest { @Tested Foo _foo; @Test void restoreInFooCallsSuper(@Mocked final Bar bar) { new Expectations() {{ invoke(bar, "restore"); }}; _foo.restore(); } }
Таким образом, в основном вы пытаетесь навязать контракт вызова супер и пытаетесь разрешить подклассы? Я думаю, что это нелегко сделать из-за динамической диспетчеризации, которая скроет поведение в Java. Я не думаю, что насмешка поймает это.
Способ гарантировать, что супер вызывается, состоял бы в том, чтобы разбить супер и расширение на 2 метода, таких как
class Foo { public final void restore() { //parent code... doRestore(); } protected void doRestore() { //empty base implementation } } class Bar extends Foo { protected void doRestore() { //do my subclass specific restore stuff here } }
Предполагается, что
super.restore()
должен делать что-то полезное нет? какая-то особая логика. В вашем тесте просто проверьте, что результат вызоваsuper.restore()
произошел.Еще один способ заглянуть в него заключается в следующем. В подклассе перед выполнением чего-либо вы реализуете
assert
, который гарантирует, что супер сделал свою работу правильно. Это более сильная проверка и хорошо известна как часть Мейера. проектирование по контракту парадигма. В этом контексте подкласс просто проверяет, что постусловие реализацииsuper.restore()
выполняется перед выполнением и с помощьюassert
Вы знаете, что она не будет работать во время модульных тестов, но также и во время тестовых интеграционных запусков вашего приложения, напримерclass Foo extends Bar{ .... @Override public void restore(){ //valid override super.restore(); assert super_restore_worked_ok_condition : "restore post-condition failed"; .... } }