源文转自:Writing common test data services for gwt-dispatch with Guic
The way it stands now after my last several posts on unit testing is that each test method in a JUnit TestCase runs its own context, including its own PersistenceManager injected with Guice. Because I’m initializing the AppEngine test environment with LocalDatastoreService.NO_STORAGE_PROPERTY = TRUE, any test data I create in one test is not available to the next test method, even in the same TestCase class. This is typical behavior for JUnit test cases, and generally a good thing as each test should be independent, but it does mean we need a convenient way to create test data. My current strategy is twofold:
Create test data used by all tests in the TestCase setUp() method that runs before each test
Create common test data (used by multiple TestCases) in test data generator services
The first problem to solve is how to get access to a dispatch service and PersistenceManager inside the test data generators. Both are now being injected by Guice as covered in previous posts, so I’ve written a BaseTestDataService that does the Guice magic:
package com.roa.test.service;
import net.customware.gwt.dispatch.client.standard.StandardDispatchService;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.roa.server.guice.ServerModule;
import com.turbomanage.gwt.server.PMF;
import com.turbomanage.gwt.server.guice.DispatchTestModule;
public class BaseTestDataService
{
protected static Injector inj = Guice.createInjector(new ServerModule(),
new DispatchTestModule());;
protected static StandardDispatchService getService()
{
return inj.getInstance(StandardDispatchService.class);
}
protected static PMF getPMF()
{
return inj.getInstance(PMF.class);
}
}
I’m intentionally using a static getPMF() method to make it as simple as possible to use the test data services in a unit test via static methods. Alternatively, I could have used instance methods and constructor injection, but then you’d have to create a new instance of a test data service in each test, which is just that much more code to write… Also, constructor injection is not possible in this case because the TestCases themselves are not instantiated by Guice, so instantiating a new test data service from a test case would not involve Guice, either.
It does not matter that the BaseTestDataService and BaseTest (below) are both calling Guice.createInjector() and thereby creating multiple Guice contexts, each having its own PMF instance. The important thing for these database tests is that they’re all going against one Datastore, not one PersistenceManager.
Here’s a simple test data generator that extends BaseTestDataService and provides a method to add a test user:
package com.roa.test.service;
import com.roa.client.domain.User;
import com.roa.shared.rpc.AddUserAction;
import com.roa.shared.rpc.AddUserResult;
public class UserTestDataService extends BaseTestDataService
{
public static User addTestUser() throws Exception
{
// Create new user
User u = new User();
u.setEmailAddress("test@example.com");
u.setFirstName("Test");
u.setLastName("User");
u.setGoogleAccountId("testAccountId");
AddUserResult userResult = (AddUserResult) getService().execute(
new AddUserAction(u));
u = userResult.getUser();
return u;
}
}
Note the call to getService() on line 17. Thanks to Guice, test data generator services can invoke gwt-dispatch ActionHandlers the same way as the tests themselves.
Finally, here’s a test case that calls the above service to create a test user in the Datastore:
package com.roa.test;
import java.util.List;
import javax.jdo.Query;
import com.appenginefan.toolkit.unittests.BaseTest;
import com.roa.client.domain.User;
import com.roa.test.service.UserTestDataService;
public class UserTestCase extends BaseTest
{
@Override
protected void setUp() throws Exception
{
super.setUp();
UserTestDataService.addTestUser();
}
public void testUserAdded() throws Exception
{
// Run tests here
Query q = pm.newQuery(User.class, "emailAddress == e");
q.declareParameters("java.lang.String e");
List<User> users = (List<com.roa.client.domain.User>) q.execute("test@example.com");
assertEquals(1, users.size());
User user = users.get(0);
assertNotNull(user.getId());
}
}
I should probably show my BaseTest method, too. I’m using AppEngineFan’s BaseTest as discussed in previous posts and modified the setUp() method for Guice injection as follows:
/**
* Sets up the App Engine environment.
*/
@Override
protected void setUp() throws Exception
{
if (initializer != null)
{
throw new UnsupportedOperationException(
"setup may only be called once!");
}
super.setUp();
initializer = new TestInitializer(getEnvironmentOrNull());
initializer.setUp();
Injector inj = Guice.createInjector(new ServerModule(),
new DispatchTestModule());
this.testSvc = inj.getInstance(StandardDispatchService.class);
this.pm = inj.getInstance(PMF.class).getPersistenceManager();
}
Thanks to Guice, we can now get access to the PersistenceManager and call ActionHandlers via a dispatch test service even from static methods in test data generators. This greatly streamlines unit testing.
分享到:
相关推荐
5. **异步通信(Ajax)**:GWT内置了异步通信机制,通过GWT的RequestBuilder或GWT-RPC(Remote Procedure Call)实现与服务器的无缝交互,实现页面的无刷新更新。 6. **本地化支持**:GWT支持多语言环境,开发者...
gwt-maven-plugin 该插件旨在通过提供两种特定的打包方式: gwt-lib和gwt-app ,使使用Maven构建GWT项目更加容易。 基本用法 将插件添加到您的POM并启用扩展: < groupId>net.ltgt.gwt.maven</ groupId> ...
怀念Gaël gwt-test-utils是用于应用程序的Java测试框架。 它提供了一种简单的方法来为GWT客户端代码编写快速的Java测试,而无需GWTTestCase或任何servlet容器实例! 这意味着您可以不受限制地使用任何Java工具:...
标题中的“gwtp-dispatch-rpc-client-1.1.1.zip”暗示了这是一个与GWTP(GWT Platform)相关的库,特别是其Dispatch RPC客户端组件的版本1.1.1。GWTP是一个基于Google Web Toolkit (GWT)的MVP框架,它提供了强大的...
标题中的“gwtp-dispatch-rpc-shared-1.2.1.zip”指示了一个与GWTP(GWT Platform)相关的开源项目版本,特别是关于Dispatch RPC共享模块的1.2.1版。GWTP是一个用于构建MVP(Model-View-Presenter)架构的框架,基于...
1. **GWT入门教程**:对于初学者,资料可能涵盖GWT的基本概念、开发环境搭建(如Eclipse插件配置)、Hello World示例、MVP(Model-View-Presenter)设计模式的介绍,以及如何创建和运行第一个GWT项目。 2. **GWT...
现在,该插件被认为是legacy GWT maven plugin (又名mojo GWT maven插件),而新插件被认为是new generation GWT maven plugin (又名tbroyer GWT maven插件)。 仍然支持旧版maven插件,但强烈建议将新插件用于新...
GWT整合Spring时需要这个包,在官网上没有最新的jar包,这是自己用jar命令生成的,并测试可以使用。
2. **gwt-dev-plugin-x86.msi**:这是一个Windows安装程序包,用于32位系统。MSI是Microsoft Installer的文件格式,用户可以通过双击此文件进行标准的Windows安装过程。 3. **gwt-dev-plugin.xpi**:这是Firefox...
Eclipse是一款广泛使用的集成开发环境(IDE),而GWT for Eclipse则是Eclipse的一个插件,专门用于支持GWT应用程序的开发。这个插件针对Eclipse的3.7和3.6版本进行了优化,以提供更好的开发体验。 GWT的核心功能...
* gwt-dispatch. Handlers are spring managed beans. * jsr-330 in client and server side. * Spring. * Spring Security. * H2 database. * Build by maven. * Runnable by jetty (mvn jetty:deploy-war). * Auto...
本文档标题为《Test-Driven-Development-with-Mockito_2013-11》,从标题可以得知本文涉及的知识点主要关于测试驱动开发(Test-Driven Development,简称TDD)和Mockito测试框架的实践应用。Sujoy Acharya是本书的...
标题中的"gwt-dev-plugin-x86-对ie浏览器使用"指的是一个特定的GWT开发插件,适用于x86架构的机器,并且是专为Internet Explorer(IE)浏览器设计的。在GWT的早期版本中,为了实现Java到JavaScript的编译和在浏览器...
这个实例“gwt-windows-1.5.2”是GWT的一个早期版本,它提供了一个在Windows环境下开发GWT应用的示例。GWT 1.5.2发布于2008年,虽然现在已经比较过时,但对于初学者来说,它仍然是一个理解GWT基本概念和工作原理的好...
**Cypal Studio for GWT** 是一个专为 **Eclipse IDE** 设计的插件,旨在简化基于 **Google Web Toolkit (GWT)** 的 **Ajax** 应用程序的开发流程。通过使用 GWT,Java 开发人员可以利用纯 Java 语言编写富互联网...
解压后的目录中包含了如 `gwt-dev-windows.jar` 和 `gwt-servlet.jar` 等库文件,它们是 GWT 开发和运行所必需的。`gwt-dev-windows.jar` 包含了 GWT 的开发工具,而 `gwt-servlet.jar` 用于服务器端支持。 9. **...