`
zhaowanhe
  • 浏览: 2343 次
  • 性别: Icon_minigender_1
  • 来自: 陕西
最近访客 更多访客>>
社区版块
存档分类
最新评论

编写可测试GWT代码的一些小经验

阅读更多

当我们谈及可测试的GWT时总是绕不开MVP模式,一些很经典的帖子里面介绍了使用MVP模式把复杂逻辑控制在Presenter中,将展示相关的逻辑(主要是涉及到GWT native代码的部分)控制在View中。这样就能够使得对主要逻辑代码的测试摆脱GWT-Testcase的束缚,尽情的使用Junit和各种Mock所带来的强力功能。遗憾的是这里有一个完美的假设:假设我们能够把所有native代码控制在View中。而实际开发中我们发现,想做到这一点非常困难。例如我们经常要在Presenter中做一些Alert或者Confirm的工作,又或者我们的一些遗留代码中使用了native方法,特别是这些方法如果使用static方法提供调用的,那简直就是异常噩梦。

把这些代码全都转移到View层中会让Presenter的代码变得支离破碎。对于这类问题我们设计了称之为Barrier的解决方案,顾名思义:Barrier是一种篱笆,在打包运行时他能够把用到了反射、mockGWT无法编译的代码单元隔离出来;在测试阶段,又可以把GWT native代码隔离开。下面是一个针对Window类的Barrier的基本结构:

 

编写可测试GWT代码的一些小经验 - robotz@yeah - IronRobot
 思路很简单,抽象一个接口出来,包含对Window的基本方法调用的封装。使用GWTWindow类实现一个ClientImplBarrier的代码也很简单,就是一个单例方法:

 

 

public static WindowInterface window;

public static WindowInterface getWindow() {         if (window == null)

            window = new WindowObjectBarrierClientImpl();

        return window;

    }

 

So easy 哈,Barrier发挥作用的关键就在这里。我们可以在unit testbefore-class中把HostImpl作为初始值赋值给windw属性。这里的HostImpl我们可以做一个简单实现,把参数打印到控制台上,或者缓存到List里面以备后面进行验证,也可以Mock一个实现出来,统统OK。(HostImpl不要放在和ClientImpl同一个目录的地方,不然GWT编译就通过不了啦)。当然需要为了隔离开而大费周折的类并不多,弄一个BarrierFacade,把常用的类都包装好,维护成本并不大。对代码的侵入性也很小。

遗憾的是,这样做我们就不能保证window属性的隐蔽性了。暂时没有想到好的解决方案。

 

另一种需要我们大费周折隔离的就是RPC调用,GWT.create一下下就可以获得一个远程调用所需要的对象,大神奇。但写单测时怎么办?如果你的Presenter中涉及到需要与服务器交互,disaster。仔细想想,其实就是所谓的RPC总是万变不离其宗的,client端把参数发到server端,server端把结果返回回来。测试时需要网络吗?需要容器吗?当然我们不需要,更不希望需要。所以我们完全可以把网络去掉,把create生成的对象和server端的实现直接绑定在一起。我们可以借助CGlib实现一个create方法达到这个目的。

下面是一个针对同步调用的rpcservicecreate的实现。Impl是一个service的实现。可以直接接上我们具体的servie的实现,不过最好还是用mock对象吧~

 

public static <T> T create(Class<T> rpcInterface, final T impl) {

        Object t = Enhancer.create(Object.class, new Class[] { rpcInterface }, new InvocationHandler() {

             @Override

            public Object invoke(Object self, Method method, Object[] args) throws Throwable {

                String methodName = method.getName();

                Class[] argTypse = method.getParameterTypes();

                Method implMethod = impl.getClass().getMethod(methodName, argTypse);

                if (implMethod == null) {

                    throw new NoSuchMethodError(methodName + " not support in class" +impl.getClass().getName());

                }

                return implMethod.invoke(impl, args);

            }

        });

        return (T) t;

    }

 


 

针对异步调用只要继承一个RequestBuilder并重写send方法就o啦,这里就不贴了

 

通过以上两个方法,我们用junit测试覆盖了大部分的Presenter层的代码,非常好用。

 

当然这还是在一个大前提下:把PresenterView做清晰的划分,这是一把双刃剑。让我们写代码的时候不再那么随心所欲,但同时也能使我们能理清自己的逻辑,写出更漂亮,更整洁的代码。

实现PV的清晰划分并不困难,我们需要明确的是PV的纽带是什么:P响应V触发的事件,V展示P的数据。所以我们是有一些原则来保证接口的明确划分的:

例如:避免V接口的方法声明中包含如getButton之类的方法。

 

另外网上有个老外做的套件叫GWT-test-utils,使用的是javaagent技术,在类加载时对native方法重写,很强大。感谢**同学总是能发现非常好用的工具。

分享到:
评论
1 楼 ccx410 2011-12-19  
安装gwt报错,unable to retrieve osgi.bundle,com.google.gwt.eclipse.sdkbundle如何解决

相关推荐

    gwt揭秘源代码

    GWT的核心概念是编译器,它将Java代码转换为优化过的JavaScript,使得开发者可以用熟悉的Java语言编写前端应用,同时享受到类型安全和强大的开发工具支持。其工作流程包括编译、优化和本地化,确保代码在各种浏览器...

    gwt入门项目代码

    8. **单元测试**:GWT提供了JUnit支持,用于编写和运行客户端代码的单元测试,了解如何编写和运行这些测试。 9. **模块化开发**:GWT支持模块化开发,通过.gwt.xml文件定义模块,理解如何组织和管理项目模块。 10....

    gwt界面编写example源代码

    在GWT项目中,`build.xml`通常包含执行GWT编译和部署的特定任务,比如`gwtc`任务用于编译GWT代码,`devmode`任务用于启动GWT开发模式服务器。 `src`目录是源代码存放的地方,其中应该包含GWT模块的Java类文件。GWT...

    GWT编写hello world

    `上.exe`和`下.exe`可能是用于辅助教学的可执行文件,它们可能包含了一些演示或练习的代码片段,帮助学习者更好地理解和实践GWT编程。 通过学习并实践这个"Hello World"教程,开发者可以了解GWT的基本工作流程,...

    GWT

    通常,这样的设计可能涉及到如何优雅地组织GWT代码结构、实现可重用的组件或遵循特定的设计原则,如MVP(Model-View-Presenter)模式,用于分离视图逻辑和业务逻辑。 标签“源码”和“工具”表明这篇博客可能探讨了...

    gwt 练习 gwt学习

    GWT允许开发者使用Java语言编写客户端代码,然后通过编译器将其转换为优化过的JavaScript,以便在各种浏览器上运行。这个“gwt 练习 gwt学习”项目可能是为了帮助用户熟悉GWT的基本概念、开发流程和最佳实践。 在...

    GWT学习经验及实例指导

    宿主模式是GWT的一个重要特性,它允许开发者在本地环境中直接运行和测试GWT应用,无需部署到Web服务器。在宿主模式下,开发者可以实时查看和调试代码,就像在开发传统的Java应用一样,极大地提高了开发和调试的效率...

    GwtDemo helloworld

    8. **单元测试**:GWT提供了JUnit支持,可以编写单元测试来验证代码的功能。在登录示例中,可能会有针对验证逻辑和RPC调用的测试。 通过深入研究这个GwtDemo helloworld项目,开发者不仅可以了解GWT的基本用法,还...

    GWT入门和进阶

    GWT的核心在于它的Java-to-JavaScript编译器,你可以像平常编写Java程序一样编写GWT代码。例如,创建UI界面可以使用`com.google.gwt.user.client.ui`包下的各种组件,如`Panel`、`Widget`等。 **3. 事件处理** GWT...

    GWTTestcase的单元测试

    在GWT项目中进行单元测试是确保代码质量、可维护性和功能正确性的重要环节。 描述虽然为空,但我们可以根据标题推测这篇博文可能详细解释了如何创建和执行GWTTestcase,这是GWT专门为测试其组件和应用程序设计的一...

    Google plugin sdk GWT

    6. **编写GWT代码**:使用GWT的模块化结构,开发者可以创建多个GWT模块,每个模块包含一组相关的类。使用Java编写业务逻辑和用户界面,GWT会自动处理跨浏览器兼容性问题。 7. **编译与测试**:通过GWT的开发服务器...

    GWT开发环境JAVA

    4. **单元测试**:GWT提供了JUnit支持,允许在客户端代码上进行单元测试。 5. **国际化的支持**:GWT提供了多语言支持,方便应用的全球化。 6. **优化的性能**:GWT的编译器通过各种优化技术,如Dead Code ...

    GWT Eclipse 3.4 插件

    GWT(Google Web Toolkit)是Google推出的一款用于开发富互联网应用程序(Rich Internet Applications,简称RIA)的开源工具,它允许开发者使用Java语言编写前端代码,然后自动编译为JavaScript,从而在浏览器上运行...

    GWTDemo

    至于压缩包内的文件 "GWTTest",这可能是项目的测试代码,包含了对GWTDemo功能的验证和测试用例,通常会使用JUnit或者其他测试框架来编写。 总结起来,GWTDemo项目是一个关于使用Google Web Toolkit开发Web应用的...

    GWT RPC详细例子:代码加文档说明

    GWT(Google Web Toolkit)是Google推出的一款开源的JavaScript开发框架,它允许开发者使用Java语言编写Web应用程序,并自动生成优化的JavaScript代码。RPC(Remote Procedure Call)是GWT中的一个核心特性,用于...

    GWT入门与经典实例解析源码

    这个框架允许开发者使用Java语言编写客户端代码,并自动编译为高效的JavaScript,从而在浏览器端运行。GWT入门与经典实例解析源码提供了一个学习和实践GWT开发的宝贵资源,下面将详细介绍GWT的关键概念、核心特性...

    GWT Eclipse 3.5 插件

    - **代码编辑支持**:集成的代码编辑器提供了语法高亮、代码提示、错误检查等功能,便于编写GWT代码。 - **设计视图**:通过可视化界面,开发者可以在设计视图中布局和预览应用界面,无需直接编写HTML和CSS。 - **...

Global site tag (gtag.js) - Google Analytics