`
dearwolf
  • 浏览: 345048 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

当Mock对象遭遇继承

OO 
阅读更多

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()重写一遍?如果要抽象出接口来,又该怎样抽象才合情合理?

恳请赐教。
分享到:
评论
4 楼 dearwolf 2007-09-25  
嗯……楼上说的有道理……不是JMock的错

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

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

对不起,耽误了大家的时间……
3 楼 javavsnet 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(汗)。
2 楼 dearwolf 2007-09-25  
我也觉得应该是在设计上的问题才导致了mock的困难,但是这问题所在是什么呢?
1 楼 gigix 2007-09-25  
首先这个继承是有问题的,因为你不能随便把一个B当作一个A来用。

相关推荐

    mock对象介绍

    ### Mock对象介绍 #### 一、引言 在软件开发过程中,单元测试是确保代码质量的重要环节。然而,在测试特定代码段时,如果该代码依赖于外部系统(如数据库访问、网络请求等),就会带来一系列挑战。为了克服这些...

    0积分:Mock对象教程

    ### 使用Mock对象在Java单元测试中的重要性及实践 #### 引言 在软件开发过程中,单元测试作为确保代码质量的重要环节,其有效性往往受到多种因素的影响,尤其是当待测方法依赖于外部资源如网络、数据库或其他复杂...

    Go-Mockcounterfeiter-一个工具用于在Go中生成自容器类型安全的测试Mock对象

    这样,当我们测试一个需要依赖其他服务或组件的函数时,可以使用Mock对象替代真实的依赖,以便在隔离的环境中验证被测试代码的行为。 使用Mock counterfeiter,开发者无需手动编写Mock对象的大量样板代码,这极大地...

    dotnet 单元测试 Mock 让一个对象继承多个接口.rar

    在上面的代码中,`Setup`方法定义了当Mock对象的`Method1`或`Method2`被调用时,它们应该返回的值。这样,即使`MyClass`在运行时依赖于这些接口,我们也可以控制它们的行为,以适应测试场景。 当我们处理一个类需要...

    基于python的mock测试数据练习

    1. `autospec=True`: 当设置为True时,mock对象会尽可能模仿原对象的行为,包括方法签名和异常处理。 2. `spec`和`spec_set`: 可以指定一个对象,让mock对象的接口与该对象一致。 通过上述方式,我们可以利用`...

    Object-CMock objects for Objective-C在Objective-C中使用Mock对象的实践

    这个项目是关于在Objective-C中使用Mock对象的实践。Mock对象是软件测试中的一种重要工具,用于模拟真实对象的行为,从而在单元测试中隔离被测代码的依赖项。本项目将介绍如何使用Objective-C的测试框架和第三方库来...

    mock学习资料

    5. **Stubbing**:这是Mock对象的一种行为配置,用于定义当某个方法被调用时,Mock对象应该如何响应。可以设定返回值、抛出异常,甚至是执行自定义的逻辑。 6. **验证(Assertion)**:在测试结束后,我们可以验证...

    Mock

    这些工具提供了方便的方法来创建和管理Mock对象,使测试过程更加便捷。例如,Mockito允许开发者通过简单的API来定义模拟对象的行为,而Sinon.js则提供了模拟函数、定时器和网络请求的能力。 Mock的基本原理是替换...

    mock学习交流

    首先,让我们了解什么是Mock对象。Mock对象是模拟真实对象的行为和状态的假对象。它们可以按照预设的返回值或行为进行响应,这在测试中非常有用,因为我们可以控制它们的行为,确保测试的隔离性。Mocking框架如...

    springboot搭建mock

    2. **创建Mock对象**:在测试类中,我们可以使用`@Mock`注解来创建Mock对象,例如: ```java @Mock private MyService myService; ``` 3. **配置Mock行为**:通过`when()`和`thenReturn()`等方法,我们可以定义...

    googlemock资料

    4. **Mock对象的生命周期**:在测试开始时创建mock对象,在测试结束时销毁。通常,它们作为局部变量在测试函数内创建,这样可以确保在每次测试之间不会有任何状态的残留。 5. **使用`Nice Mock`和`Strict Mock`**:...

    16、使用Mock修复测试代码1

    在这个资源中,我们将学习如何使用Mock对象来修复测试代码。Mock对象是PHPUnit测试框架中的一种重要工具,用于模拟对象的行为,从而使测试代码更加灵活和可靠。 标题中提到的“使用Mock修复测试代码1”指的是使用...

    单元测试与 Mock 方法

    3. 激活Mock对象:使用EasyMock.replay()将Mock对象从配置模式切换到运行模式,使其开始响应预期的调用。 4. 执行测试:运行包含Mock对象的测试代码。 5. 验证结果:使用EasyMock.verify()检查Mock对象的所有预期...

    Go-goautomock使用gogenerate从接口自动生成mock

    在测试中,mock对象是一种常用的工具,它们可以模拟复杂的依赖关系,使我们能够在独立环境中测试单个组件。"Go-generate"是Go语言提供的一种自动化工具,允许我们在构建过程中执行自定义的代码生成任务。本文将深入...

    5-Mock+EasyMock.rar

    在软件开发中,特别是使用面向对象编程时,Mock对象是一种重要的测试策略,它用于替代真实对象以隔离被测试代码,确保测试的准确性。 Mock对象的主要目的是为了模拟那些复杂或者不可控的依赖关系,例如外部服务、...

    C++ mock框架mockcpp

    在单元测试中,mock对象是代替真实对象使用的,它能模拟真实对象的行为,以便测试代码能够独立于其他系统组件进行执行。Mockcpp提供了一种机制,允许开发者创建这些模拟对象,设置它们的期望行为,并验证这些行为...

    Mock.java.zip

    在这个例子中,`mockedList`是Mock对象,`when`方法用于配置Mock对象的行为,而`verify`方法用于检查Mock对象是否按照预期被调用。 **EasyMock**是另一个Mocking框架,它的使用方式略有不同,但同样强大。EasyMock...

Global site tag (gtag.js) - Google Analytics