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

窥探EasyMock(3)动态代理技术

阅读更多

EasyMock的实现使用了动态代理(Dynamic Proxy) 技术。动态代理工具是 java.lang.reflect 包的一部分,在 JDK 1.3 版本中添加到 JDK,它允许程序创建代理对象,代理对象能实现一个或多个已知接口,并用反射代替内置的虚方法分派,分派对接口方法的调用。这个过程允许实现“截取”方法调用,重新路由它们或者动态地添加功能。

 

动态代理机制的核心是InvocationHandler 接口:

 

public interface InvocationHandler {
    Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}
 

例子,下面这个handler为所有的方法调用添加了log:

 

public class LogEnabler<T> implements InvocationHandler {

        private T t;

        public LogEnabler(T t) {
            this.t = t;
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            LOG.info("Before invocation to " + method.getName() + ".");
            Object result = method.invoke(t, args);
            LOG.info("After invocation to " + method.getName() + ".");
            return result;
        }

    }

 

看到了AOP的影子了么?事实上如structs2中interceptor的实现就是使用了动态代理技术。

 

同样,EasyMock的核心技术也是使用了动态代理,可以看到createMock方法的代码如下:

 

public <T> T createMock(Class<T> toMock) {
        try {
            state.assertRecordState();
            IProxyFactory<T> proxyFactory = createProxyFactory(toMock);
            return proxyFactory.createProxy(toMock, new ObjectMethodsFilter(
                    toMock, new MockInvocationHandler(this), null));
        } catch (RuntimeExceptionWrapper e) {
            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
        }
}

 

它使用了ProxyFactory来为被mock的类创建了一个代理对象。ProxyFactory的实现如下:

 

public class JavaProxyFactory<T> implements IProxyFactory<T> {
    @SuppressWarnings("unchecked")
    public T createProxy(Class<T> toMock, InvocationHandler handler) {
        return (T) Proxy.newProxyInstance(toMock.getClassLoader(),
                new Class[] { toMock }, handler);
    }
}

 

显而易见,创建mock对象最核心的就是拦截方法调用,用期望的行为和返回结果代替。那就来看看ObjectMethodsFilter这个拦截类。这个类拦截了Object类中三个基本方法的调用,而把被mock类其它方法的调用转发至MockInvocationHandler这个delegate处理:

 

public final Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if (equalsMethod.equals(method)) {
            return Boolean.valueOf(proxy == args[0]);
        }
        if (hashCodeMethod.equals(method)) {
            return Integer.valueOf(System.identityHashCode(proxy));
        }
        if (toStringMethod.equals(method)) {
            return mockToString(proxy);
        }
        return delegate.invoke(proxy, method, args);
}

 

关于EasyMock对于record,replay和verify的具体实现,且听下回分解。

分享到:
评论

相关推荐

    EasyMock

    在源码层面,EasyMock的工作原理是通过动态代理生成模拟对象。当你创建一个模拟对象时,实际上EasyMock会生成一个实现了目标接口的代理类。在这个代理类中,所有方法的调用都会被拦截,然后根据你在测试前设定的预期...

    easyMock

    EasyMock支持动态mocking,这意味着可以在运行时改变模拟对象的行为。这在测试中非常有用,因为可以根据测试需求灵活地调整模拟对象的响应。 **4. 高级特性** - **回调**:使用`doAnswer()`方法,可以指定当方法被...

    EasyMock介绍和使用

    EasyMock的工作原理基于动态代理。在测试开始时,EasyMock会生成一个实现了所需接口的代理对象,这个代理对象会记录所有对它的调用。在测试执行期间,你可以预设这个代理对象的行为,如返回特定值、抛出异常等。测试...

    Easymock学习笔记

    EasyMock通过动态代理机制生成Mock对象,它在运行时动态创建实现了指定接口的类,这样在测试中就可以使用这些Mock对象来替代真实的依赖,使得测试更加可控和独立。使用EasyMock进行单元测试,可以提高测试覆盖率,...

    easymock资料和源代码实例

    Easymock的核心是通过反射和动态代理来实现模拟对象的创建。它首先创建一个与被模拟接口相同类型的动态代理对象,然后在这个代理对象上设置期望行为。在测试过程中,调用这个代理对象实际上就是在调用模拟对象,...

    easymock.jar,easymockclassextension.jar

    3. **验证**:在测试完成后,Easymock会验证模拟对象的行为是否符合你的预期。如果不符合,它将抛出一个异常,帮助你找出代码中的问题。 4. **部分模拟**:Easymock支持部分模拟,这意味着你可以只模拟一个类的部分...

    EasyMock 简介

    通过 EasyMock,我们可以为指定的接口动态的创建 Mock 对象,并利用 Mock 对象来模拟协同模块或是领域对象,从而使单元测试顺利进行。这个过程包括: 1. 记录(Record): EasyMock 记录 Mock 对象的行为,以便在...

    easymock-3.2.zip

    3. **示例文档**:这些示例通常是一些简单的代码片段,展示了如何在实际项目中应用EasyMock。它们可以作为起点,帮助初学者快速上手。 4. **所需jar包**:这是EasyMock运行所需的库文件。在Java项目中,你需要将...

    easymock2.4+EasyMock使用简明手册.pdf

    4. **动态mocking**:除了静态地设置期望,EasyMock 2.4还支持动态mocking,这意味着在运行时可以改变模拟对象的行为。 三、使用步骤 1. **创建模拟对象**:使用`EasyMock.createMock()`方法创建模拟对象。 2. **...

    模拟测试辅助工具easyMock.zip

    EasyMock 是一套通过...EasyMock 提供了根据指定接口动态构建 Mock 对象的方法,避免了手工编写 Mock 对象。本文将向您展示如何使用 EasyMock 进行单元测试,并对 EasyMock 的原理进行分析。 标签:easyMock

    easymock的使用,含demo

    EasyMock 是一套通过简单的方法对于指定的接口或...EasyMock 提供了根据指定接口动态构建 Mock 对象的方法,避免了手工编写 Mock 对象。本文将向您展示如何使用 EasyMock 进行单元测试,并对 EasyMock 的原理进行分析。

    easymock-3.2.jar

    EasyMock主要是为测试提供模拟数据,比如你可以模拟HttpServletRequest。

    easymock-4.2.jar

    EasyMock 是一套通过简单的方法对于指定的接口或类生成 Mock 对象的类库,它能利用对接口或类的模拟来辅助单元测试。...EasyMock 提供了根据指定接口动态构建 Mock 对象的方法,避免了手工编写 Mock 对象。

    EasyMock 实例

    3. **启动模拟**:调用`EasyMock.replay()`方法开始执行模拟。在这个阶段,模拟对象的行为将按照你设定的期望进行。 ```java EasyMock.replay(myServiceMock); ``` 4. **执行测试**:现在,你可以像操作真实对象...

    easyMock2.2.doc

    它通过动态代理或子类化技术来实现,允许开发者预定义对象行为,从而简化了对依赖项的测试。EasyMock2.2版本相较于早期版本(如EasyMock1.x),在使用方式和功能上进行了显著的改进,使其更加灵活和易于使用。 ####...

    easymock.jar包

    此外,Easymock 3.3版本引入了一些增强特性,比如对Java代理的支持,使得模拟静态方法成为可能,这对于测试那些依赖静态方法的代码非常有帮助。同时,它也支持了Java 8的新特性,如Lambda表达式和Stream API。 总结...

    EasyMock的安装与部署所需全部文件.zip

    EasyMock是一款强大的模拟框架,主要用于Java单元测试。它允许开发者创建和控制对象的模拟行为,以便在测试过程中隔离被测试代码。在这个“EasyMock的安装与部署所需全部文件.zip”压缩包中,包含了在Windows环境下...

    EasyMock 架包

    EasyMock的工作原理是基于Java代理机制,它动态地创建实现了所需接口的模拟对象。通过这些模拟对象,我们可以设置期望(Expectations),定义当某个方法被调用时,模拟对象应如何行为。例如,我们可以设置一个方法在...

Global site tag (gtag.js) - Google Analytics