- class A{
- public String a(){
- return a;
- }
- }
- public class B extends A{
- public String b(){
- return b;
- }
- }
上面所示的是一个很常见的继承结构,但是就是这样的结构导致了在Mock对象时会产生某些令人困惑的问题。
假如在BConsumer这个类中用到了B,那么就需要把B的实例(这里先不讨论应该抽象出接口与否的问题)注入到BConsumer中去。如果我们要模拟的是b()这个方法,那自然一切都没问题。我这里用的是JMock来mock具体类:
java 代码
- Mockery context = new JUnit4Mockery() {
- {
- setImposteriser(ClassImposteriser.INSTANCE);
- }
- };
- ……
- @Test
- public void xxx(){
- BConsumer consumer = new BConsumer();
- B b = context.mock(B.class);
- context.checking(new Expectations(){{
- allowing(b).b();
- }});
- consumer.setB(b);
- ……
- }
可是如果我们需要模拟a()这个方法时,问题就出现了。
java 代码
- @Test
- public void xxxxx(){
- BConsumer consumer = new BConsumer();
- B b = context.mock(B.class);
- context.checking(new Expetations(){{
- allowing(b).a();
- }});
- consumer.setB(b);
- ……
- }
我们可以按照上面这种方式来写Mock么?当然不行!我们Mock的是B,但是实际调用的则是A中的方法a()!
那么可能就有人想到或许可以这样做:
java 代码
- @Test
- public void xxxxx(){
- BConsumer consumer = new BConsumer();
- A a = context.mock(A.class);
- context.checking(new Expetations(){{
- allowing(a).a();
- }});
- consumer.setB((B)a);
- ……
- }
但实际上,到了 consumer.setB((B)a);这一步的时候,我们得到的a实际上是通过cglib生成的对象,要转型成B就会出现ClassCastException。
那我们到底该怎么做才好呢?难道为了Mock测试的需要,就在B中把A中的a()重写一遍?如果要抽象出接口来,又该怎样抽象才合情合理?
恳请赐教。