验证是否调用了受保护的超级方法

时间:2013-01-11 20:35:04

标签: java junit verification jmockit

我有以下结构:

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)FooTestFoo一起存在于单独的项目(因此文件夹)与{{{ 1}}。

反正有没有达到预期的测试?我检查了jMockit tutorials(过去几个月多次)并没有看到类似的测试(在Google上进行搜索也是如此)。


更新

在回复的帮助下,我理解强制执行子类来调用Bar并不是最好的做法,但这不是我的实现,我仍然必须测试它。我仍在寻找一种方法来强制执行我的jUnit测试,以检查对父母的调用是否正在进行。

3 个答案:

答案 0 :(得分:4)

所以基本上你是在试图强制调用super并尝试允许子类化的契约?我认为由于动态调度将隐藏Java中的行为,因此不容易做到这一点。我不认为Mocking会抓住这个。

确保super被调用的方法是将超级和扩展分解为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
    } 
}

答案 1 :(得分:1)

super.restore()应该做些有用的事吗?一些具体的逻辑。在您的测试中,只需测试调用super.restore()的结果即可。

另一种研究方法如下。在做任何事情之前的子类中,你实现了一个assert 确保超级正确地完成了它的工作。这是一个更强大的检查,并且是众所周知的Meyer的 Design by Contract 范例的一部分。在此上下文中,子类只是检查super.restore()实现的后置条件在执行之前是否成立,并且使用assert您知道它将在单元测试期间失败,但也会在应用程序的测试集成运行期间失败,例如< / p>

class Foo extends Bar{
    ....

    @Override
    public void restore(){  //valid override
        super.restore();
        assert super_restore_worked_ok_condition : "restore post-condition failed";

        ....
    }
}

答案 2 :(得分:1)

以下测试应该有效:

public class FooTest
{
    @Tested Foo _foo;

    @Test
    void restoreInFooCallsSuper(@Mocked final Bar bar)
    {
        new Expectations() {{
            invoke(bar, "restore");
        }};

        _foo.restore();
    }
}