论坛首页 综合技术论坛

当Mock对象遭遇继承

浏览 5262 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-09-25  

java 代码
  1. class A{
  2. public String a(){
  3. return a;
  4. }
  5. }
  6. public class B extends A{
  7. public String b(){
  8. return b;
  9. }
  10. }

上面所示的是一个很常见的继承结构,但是就是这样的结构导致了在Mock对象时会产生某些令人困惑的问题。

假如在BConsumer这个类中用到了B,那么就需要把B的实例(这里先不讨论应该抽象出接口与否的问题)注入到BConsumer中去。如果我们要模拟的是b()这个方法,那自然一切都没问题。我这里用的是JMock来mock具体类:

java 代码
  1. Mockery context = new JUnit4Mockery() {
  2. {
  3. setImposteriser(ClassImposteriser.INSTANCE);
  4. }
  5. };
  6. ……
  7. @Test
  8. public void xxx(){
  9. BConsumer consumer = new BConsumer();
  10. B b = context.mock(B.class);
  11. context.checking(new Expectations(){{
  12. allowing(b).b();
  13. }});
  14. consumer.setB(b);
  15. ……
  16. }


可是如果我们需要模拟a()这个方法时,问题就出现了。

java 代码
  1. @Test
  2. public void xxxxx(){
  3. BConsumer consumer = new BConsumer();
  4. B b = context.mock(B.class);
  5. context.checking(new Expetations(){{
  6. allowing(b).a();
  7. }});
  8. consumer.setB(b);
  9. ……
  10. }

我们可以按照上面这种方式来写Mock么?当然不行!我们Mock的是B,但是实际调用的则是A中的方法a()!

那么可能就有人想到或许可以这样做:

java 代码
  1. @Test
  2. public void xxxxx(){
  3. BConsumer consumer = new BConsumer();
  4. A a = context.mock(A.class);
  5. context.checking(new Expetations(){{
  6. allowing(a).a();
  7. }});
  8. consumer.setB((B)a);
  9. ……
  10. }

但实际上,到了consumer.setB((B)a);这一步的时候,我们得到的a实际上是通过cglib生成的对象,要转型成B就会出现ClassCastException。

那我们到底该怎么做才好呢?难道为了Mock测试的需要,就在B中把A中的a()重写一遍?如果要抽象出接口来,又该怎样抽象才合情合理?

恳请赐教。
   发表时间:2007-09-25  
首先这个继承是有问题的,因为你不能随便把一个B当作一个A来用。
0 请登录后投票
   发表时间:2007-09-25  
我也觉得应该是在设计上的问题才导致了mock的困难,但是这问题所在是什么呢?
0 请登录后投票
   发表时间:2007-09-25  

@Test
public void xxx(){
BConsumer consumer = new BConsumer();
B b = context.mock(B.class);
context.checking(new Expectations(){{
allowing(b).a();
}});
consumer.setB(b);
……
}

根据我的理解,理论上这里是不应该出问题的。B作为A的子类,当然可以调用A的方法,作为mock的B类对象,同样应该支持对A的方法的调用。否则这个mock的B就不是A的子类了,就破坏了OO中对继承的定义。
这里不是楼主的问题,应该是JMock的问题,虽然我还没有用过JMock(汗)。
0 请登录后投票
   发表时间:2007-09-25  
嗯……楼上说的有道理……不是JMock的错

刚刚写了几个类来测试了一些,实际上那段代码是可以通过的……汗……

我帖子中的问题是源于别人所提供的一些legacy代码,又仔细看了一下,原来在父类的方法声明中,有一个final修饰符……

对不起,耽误了大家的时间……
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics