随笔 - 23  文章 - 11  trackbacks - 0
<2024年3月>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

常用链接

留言簿(3)

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

在WebWork2.2中和Spring的结合变得简单了,WebWork的Action的也可以由Spring来管理。但是如何进行测试了,在google上搜了一下,其代码都是如下形式:
 1        Map params = new HashMap();
 2        params.put("a""test");
 3               Map paramCtx = new HashMap();
 4        paramCtx.put(ActionContext.PARAMETERS, params);
 5                ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy("/organiz""new_depart", paramCtx, falsefalse);
 6        proxy.setExecuteResult(false);
 7        assertEquals(proxy.execute(), "success");
 8
 9        MyTestAction action = (MyTestAction) proxy.getAction();
10        assertEquals(action.getA(), "test");

该代码执行时会报错误,查看了一下源代码应该加入
1paramCtx.put(ActionContext.DEV_MODE, Boolean.FALSE);

其次需要加载spring的applicationContext,代码如下:
1SpringObjectFactory objectFactory = new SpringObjectFactory();
2        ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
3        objectFactory.setApplicationContext(appContext);
4        ObjectFactory.setObjectFactory(objectFactory);


posted @ 2012-02-28 22:53 小小~咖啡豆 阅读(171) | 评论 (0)编辑 收藏
1.编译乱码,设置编译的字符集编码和环境编码
<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.4</source>
                    <target>1.4</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
设置环境变量MAVEN_OPTS=-Xms64m -Xmx128m -Dfile.encoding=UTF-8
2.运行mvn test时乱码(IDE上运行TestCase时OK,但是运行maven test乱码,结果测试不通过)修改pom.xml增加如下内容即可
<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.7.2</version>
                <configuration>
                    <forkMode>once</forkMode>
                    <argLine>-Dfile.encoding=UTF-8</argLine>
                    <systemProperties>
                        <property>
                            <name>net.sourceforge.cobertura.datafile</name>
                            <value>target/cobertura/cobertura.ser</value>
                        </property>
                    </systemProperties>
                </configuration>
            </plugin>
posted @ 2011-06-30 02:15 小小~咖啡豆 阅读(1497) | 评论 (1)编辑 收藏
<title>屏蔽鼠标右键、Ctrl+n、shift+F10、F5刷新、退格键</title>
</head>
<body onkeydown="KeyDown()"
oncontextmenu="event.returnValue=false">

<script language="Javascript"><!--
//屏蔽鼠标右键、Ctrl+n、shift+F10、F5刷新、退格键
//Author: meizz(梅花雨) 2002-6-18

function KeyDown(){
if ((window.event.altKey)&&
((window.event.keyCode==37)|| //屏蔽 Alt+ 方向键 ←
(window.event.keyCode==39))){ //屏蔽 Alt+ 方向键 →
alert("不准你使用ALT+方向键前进或后退网页!");
event.returnValue=false;
}

/* 注:这还不是真正地屏蔽 Alt+ 方向键,
因为 Alt+ 方向键弹出警告框时,按住 Alt 键不放,
用鼠标点掉警告框,这种屏蔽方法就失效了。以后若
有哪位高手有真正屏蔽 Alt 键的方法,请告知。*/

if ((event.keyCode==8) || //屏蔽退格删除键
(event.keyCode==116)|| //屏蔽 F5 刷新键
(event.ctrlKey && event.keyCode==82)){ //Ctrl + R
event.keyCode=0;
event.returnValue=false;
}
if ((event.ctrlKey)&&(event.keyCode==78)) //屏蔽 Ctrl+n
event.returnValue=false;
if ((event.shiftKey)&&(event.keyCode==121)) //屏蔽 shift+F10
event.returnValue=false;
if (window.event.srcElement.tagName == "A" && window.event.shiftKey)
window.event.returnValue = false; //屏蔽 shift 加鼠标左键新开一网页
if ((window.event.altKey)&&(window.event.keyCode==115)){ //屏蔽Alt+F4
window.showModelessDialog("about:blank","","dialogWidth:1px;dialogheight:1px");
return false;}
}
/* 另外可以用 window.open 的方法屏蔽 IE 的所有菜单
第一种方法:
window.open("你的.htm", "","toolbar=no,location=no,directories=no,menubar=no,scrollbars=no,resizable=yes,status=no,top=0,left=0")
第二种方法是打开一个全屏的页面:
window.open("你的.asp", "", "fullscreen=yes")
*/
// --></script>
<h2 align=center>屏蔽鼠标右键、Ctrl+n、shift+F10、F5刷新、退格键</h2>
</body>
</html>

<div style="position: absolute; top: 10; right: 10; width: 148; height: 18;cursor:hand">
<input type="button" name="Button" value="查看源代码" onClick= 'window.location = "view-source:" + window.location.href'></div>
posted @ 2008-09-23 16:12 小小~咖啡豆 阅读(474) | 评论 (0)编辑 收藏

数据库测试

在创建企业级应用的时候,数据层的单元测试因为其复杂性往往被遗弃,Unitils大大降低了测试的复杂性,使得数据库的测试变得容易并且易维护。已下介绍databasemodule和dbunitmodule进行数据库的单元测试。

用dbUnit管理测试数据

数据库的测试应该在单元测试数据库上运行,单元测试数据库给我们提供了一个完整的并有着很好细粒度控制的测试数据,DbUnitModule是在dbunit的基础上进一步的为数据库的测试提供数据集的支持。

加载测试数据集

让我们以UserDAO中一个简单的方法findByName(检查姓氏和名字)为例子开始介绍。他的单元测试如下:

@DataSet

public class UserDAOTest extends UnitilsJUnit4 {

    @Test

    public void testFindByName() {

        User result = userDao.findByName("doe", "john");

        assertPropertyLenEquals("userName", "jdoe", result);

    }

    @Test

    public void testFindByMinimalAge() {

        List<User> result = userDao.findByMinimalAge(18);        

        assertPropertyLenEquals("firstName", Arrays.asList("jack"), result);

    }

}

    @DateSet 注解表示了测试需要寻找dbunit的数据集文件进行加载,如果没有指明数据集的文件名,则Unitils自动在class文件的同目录下加载文件名为 className.xml的数据集文件。(这种定义到class上面的数据集称为class级别的数据集)

    数据集 文件必须是dbunit的FlatXMLDataSet文件格式,其中包含了所要测试的数据。测试数据库表中所有的内容将会被删除,然后再插入数据集中的 数据。如果表不属于数据集中的,哪么该表的数据将不会被删除。你也可以明确的加入一个空的表元素,例如<MY_TABLE/>(可以达到删除 测试数据库表中内容的作用),如果要明确指定一个空的值,那么使用值[null]。

   为UserDAOTest我们创建一个数据集,并放在UserDAOTest.class文件同目录下。

<?xml version='1.0' encoding='UTF-8'?>

<dataset>

    <usergroup name="admin" />  

    <user userName="jdoe"  name="doe"   firstname="john"   userGroup="admin" />

    <usergroup name="sales" />    

    <user userName="smith" name="smith" userGroup="sales" />

    

</dataset>

   测试运行的时候,首先将删除掉usergroup表和user表中的所有内容,然后将插入数据集中的内容。其中name为smith的firstname的值将会是null。

   假设testFindByMinimalAge()方法将使用一个特殊的数据集而不是使用class级别的数据集,你可以定义一个UserDAOTest.testFindByMinimalAge.xml 数据集文件并放在测试类的class文件同目录下。

<?xml version='1.0' encoding='UTF-8'?>

<dataset>

    <user userName="jack" age="18" />

    <user userName="jim"  age="17" />

</dataset>

这时,你在testFindByMinimalAge()方法使用@DataSet注解,他将覆盖class级的数据集

public class UserDAOTest extends UnitilsJUnit4 {

@Test

@DataSet("UserDAOTest.testFindByMinimalAge.xml")

public void testFindByMinimalAge() {

List<User> result = userDao.findByMinimalAge(18); 

assertPropertyLenEquals("firstName", Arrays.asList("jack"), result);

}

}

不要过多的使用method级的数据集,因为过多的数据集文件意味着你要花大量的时间去维护,你优先考虑的是使用class级的数据集。

配置数据集加载策略

缺省情况下数据集被写入数据库采用的是clean insert策略。这就意味着数据在被写入数据库的时候是会先删除数据集中有使用的表的数据,然后在将数据集中的数据写入数据库。加载策略是可配额制的,我们通过修改DbUnitModule.DataSet.loadStrategy.default 的属性值来改变加载策略。假设我们在unitils.properties属性文件中加入以下内容:

DbUnitModule.DataSet.loadStrategy.default=org.unitils.dbunit.datasetloadstrategy.InsertLoadStrategy 

这时加载策略就由clean insert变成了insert,数据已经存在表中将不会被删除,测试数据只是进行插入操作。

加载策略也可以使用@DataSet的注解属性对单独的一些测试进行配置:

@DataSet(loadStrategy = InsertLoadStrategy.class) 

对于那些树形DbUnit的人来说,配置加载策略实际上就是使用不同的DatabaseOperation,以下是默认支持的加载策略方式:

CleanInsertLoadStrategy: 先删除dateSet中有关表的数据,然后再插入数据。

InsertLoadStrategy: 只插入数据。

RefreshLoadStrategy: 有同样key的数据更新,没有的插入。

UpdateLoadStrategy: 有同样key的数据更新,没有的不做任何操作。

配置数据集工厂

 在Unitils中数据集文件采用了multischema xml 格式,这是DbUnits的FlatXmlDataSet 格式的扩展。配置文件格式和文件的扩展可以采用DataSetFactory 

虽然Unitils当前只支持一种数据格式,但是我们可以通过实现DataSetFactory来使用其他文件格式。当你想使用excel而不是xml格式的时候,可以通过unitils.property中的DbUnitModule.DataSet.factory.default 属性和@DataSet 注解来创建一个DbUnit's XlsDataSet 实例。

验证测试结果

有些时候我们想在测试时完毕后使用数据集来检查数据库中的内容,举个例子当执行完毕一个存储过程后你想检查一下啊数据是否更新了没有。

下面的例子表示的是禁用到一年内没有使用过的帐户

public class UserDAOTest extends UnitilsJUnit4 { 

    @Test @ExpectedDataSet 

    public void testInactivateOldAccounts() { 

        userDao.inactivateOldAccounts(); 

    } 

注意在test方法上增加了一个@ExpectedDataSet 注解。这将指明unitils将使用UserDAOTest.testInactivateOldAccounts-result.xml 这个数据集的内容和数据库的内容进行比较。

<?xml version='1.0' encoding='UTF-8'?> 

<dataset> 

    <user userName="jack" active="true" /> 

    <user userName="jim"  active="false" /> 

</dataset> 

根据这个数据集,将会检查是否有两条和记录集的值相同的记录在数据库中。而其他的记录和表将不理会。

使用的是@DataSet 注解的话,文件名可以明确指出,如果文件名没有明确指出来,那么文件名将匹配className .methodName -result.xml 

使用少使用结果数据集,加入新的数据集意味着更多的维护。替代方式是在代码中执行相同的检查(如使用一个findactiveusers()方法)。

使用多模式的数据集

一个程序不单单只是连接一个数据库shema。Unitils采用了扩展的数据集xml来定义多schemas下的数据。以下就是一个读取数据到2个不同的schemas中的例子:

<?xml version='1.0' encoding='UTF-8'?> 

<dataset xmlns="SCHEMA_A" xmlns:b="SCHEMA_B"> 

    <user id="1" userName="jack" />     

    <b:role id="1" roleName="admin" /> 

</dataset> 

在这个例子中我定义了两个schemas,SCHEMA_A 和 SCHEMA_B第一个schema,SCHEMA_A 被连接到默认的xml命名空间中,第二个schema,SCHEMA_B 被连接到命名空间b。如果表xml元素的前缀使用了命名空间b,那么该表就是schema SCHEMA_B 中的,如果没有使用任何的命名空间那么该表将被认为是SCHEMA_A  

中的。以上例子中测试数据定义了表SCHEMA_A.user SCHEMA_B.role

如果在数据集中没有配置一个默认的命名空间,那么将会采用在unitils.properties中的属性database.schemaNames 的第一个值作为默认的

database.schemaNames=SCHEMA_A, SCHEMA_B 

这个配置将SCHEMA_A 作为缺省的schema,这样你可以简化数据集的声明。

<?xml version='1.0' encoding='UTF-8'?> 

<dataset xmlns:b="SCHEMA_B"> 

    <user id="1" userName="jack" />     

    <b:role id="1" roleName="admin" /> 

</dataset> 

连接测试数据库 

在以上所有的例子中,我们都有一件重要的事情没有做:当我们进行测试的时候,怎样连接数据库并得到DataSource

当测试套件的第一个测试数据库的案例运行的时候,Unitils将会通过属性文件创建一个DataSource 的实例来连接你单元测试时的数据库,以后的测试中都将使用这个DataSource 实例。连接配置的详细内容如下:

database.driverClassName=oracle.jdbc.driver.OracleDriver 

database.url=jdbc:oracle:thin:@yourmachine:1521:YOUR_DB 

database.userName=john 

database.password=secret 

database.schemaNames=test_john 

配置章节所说的那样,你可以将连接数据库的驱动类和url地址配置到unitils.properties 中去,而用户名,密码以及schema可以配置到unitils-local.properties 中去,这样可以让开发人员连接到自己的单元测试数据库中进行测试而不会干预到其他的人。

在属性或者setter方法前使用注解@TestDataSource ,将会将DataSource 实例注入到测试实例中去,如果你想加入一些代码或者配置一下你的datasource,你可以做一个抽象类来实现该功能,所有的测试类都继承该类。一个简单的例子如下:

public abstract class BaseDAOTest extends UnitilsJUnit4 { 

    @TestDataSource 

    private DataSource dataSource; 

     

    @Before     

    public void initializeDao() { 

        BaseDAO dao = getDaoUnderTest(); 

        dao.setDataSource(dataSource); 

    } 

    protected abstract BaseDAO getDaoUnderTest(); 

上面的例子采用了注解来取得一个datasource的引用,另外一种方式就是使用DatabaseUnitils.getDataSource() 方法来取得datasource。

事务

出于不同的原因,我们的测试都是运行在一个事务中的,其中最重要的原因如下:

数据库的很多action都是在事务正常提交后才做,如SELECT FOR UPDATE 和触发器

许多项目在测试数据的时候都会填写一些测试数据,每个测试运行都会修改或者更新了数据,当下一个测试运行的时候,都需要将数据回复到原有的状态。

如果使用的是hibernate或者JPA的时候,都需要每个测试都运行在事务中,保证系统的正常工作。

缺省情况下,事务管理是disabled的,事务的默认行为我们可以通过属性文件的配置加以改变:

DatabaseModule.Transactional.value.default=commit 

采用这个设置,每个的测试都将执行commit,其他的属性值还有rollback disabled 

我们也可以通过在测试类上使用注解@Transactional 来改变默认的事务设置,如:

@Transactional(TransactionMode.ROLLBACK) 

public class UserDaoTest extends UnitilsJUnit4 { 

通过这种class上注解的事务管理,可以让每个测试都确保回滚,@Transactional 注解还可以继承的,因此我们可以将其放在父类中,而不必每个子类都进行声明。

.........

如果你使用Unitils的spring支持(见使用spring进行测试)你如果配置了PlatformTransactionManager 的bean,那么unitils将会使用这个事务管理。

posted @ 2008-08-25 15:11 小小~咖啡豆 阅读(1914) | 评论 (2)编辑 收藏
1、使用Dir:  
If   Dir$(dirName,   ATTR_DIRECTORY)   =   ""   Then  
  'Directory   does   not   exist  
Else  
  'Directory   does   exist  
End   If  
2、使用FileSystemObject:  
Set   objFSO   =   CreateObject("Scripting.FileSystemObject")  
   
If   objFSO.FolderExists(dirName)   Then  
  'Directory   does   exist  
Else  
  'Directory   does   not   exist  
End   If
posted @ 2008-07-04 10:06 小小~咖啡豆 阅读(645) | 评论 (0)编辑 收藏

Unitils模块

配置

和大多数的项目一样,unitils也需要一些配置,默认情况下有3个配置,每个配置都覆写前一个的配置

  1. unitils-default.properties 默认的配置,在unitils发行包中。
  2. unitils.properties 可包含项目的全部配置
  3. unitils-local.properties 可以包含用户特定配置

第一个配置文件unitils-default.properties,它包含了缺省值并被包含在unitils的发行包中。我们没有必要对这个文件进行修改,但它可以用来作参考。

第二个配置文件unitils.properties,它是我们需要进行配置的文件,并且能覆写缺省的配置。举个例子,如果你的项目使用的是oracle数据库,你可以创建一个unitils.properties文件并覆写相应的driver class和database url。

database.driverClassName=oracle.jdbc.driver.OracleDriver
database.url=jdbc:oracle:thin:@yourmachine:1521:YOUR_DB

这个文件并不是必须的,但是一旦你创建了一个,你就需要将该文件放置在项目的classpath下

最后一个文件,unitils-local.properties是可选的配置文件,它可以覆写项目的配置,用来定义开发者的具体设置,举个例子来说,如果每个开发者都使用自己的数据库schema,你就可以创建一个unitils-local.properties为每个用户配置自己的数据库账号、密码和schema。

database.userName=john
database.password=secret
database.schemaNames=test_john

每个unitils-local.properties文件应该放置在对应的用户文件夹中(System.getProperty("user.home"))。

本地文件名unitils-local.properties也可以通过配置文件定义,在unitils.properties覆写unitils.configuration.localFileName就可以。

unitils.configuration.localFileName=projectTwo-local.properties

 

启用你的unitils

unitils的功能是依赖于基础的测试框架,要使用unitils的功能,就必须先enable他们,这样做的目的也是为了容易扩展。目前支持的框架有:

  1. JUnit3 :org.unitils.UnitilsJUnit3
  2. JUnit4 :org.unitils.UnitilsJUnit4
  3. TestNG:org.unitils.UnitilsTestNG

举个例子,如果使用JUnit3,你要使用unitils

import org.unitils.UnitilsJUnit3;
public class MyTest extends UnitilsJUnit3 {
}

通常你将创建你自己的包含一些公共行为的测试基类,如dataSource的注入,你可以让这个基类继承unitils测试类。

当你使用的是JUnit4的话,你也可是使用@RunWith来代替继承unitils测试类

import org.junit.runner.RunWith;
import org.unitils.UnitilsJUnit4TestClassRunner;
@RunWith(UnitilsJUnit4TestClassRunner.class)
public class MyTest {
}

 

模块系统

在开始举例之前,让我们先了解一下unitils概念。

unitils的结构被设计成了十分容易扩展,每个模块提供了一种服务,当执行Test的时候通过TestListener调用相应的服务。

image

这种设计采用了一个统一的方式提供服务,如果你需要加入其他的服务,无需去改编测试基类(UnitilsJUnit4这些类)。要加入新的服务只需要添加一个新的模块并在unitls配置文件中登记这个模块。

目前unitils中所有有效的模块如下:

  1. DatabaseModule 数据库单元测试的维护和连接池。
  2. DbUnitModule 使用DBUnit来管理测试数据。
  3. hibernatemodule 支持Hibernate的配置和自动数据库映射检查。
  4. EasyMockModule 支持创建mock和宽松的反射参数匹配。
  5. InjectModule 支持在一个对象中注入另一个对象。
  6. SpringModule 支持加载spring的上下文配置,并检索和Spring Bean注入。
posted @ 2008-04-07 00:45 小小~咖啡豆 阅读(2769) | 评论 (2)编辑 收藏

      单元测试应该是简单和直观的,而现实中的项目大多都是采用多层方式的,如EJB和hibernate的数据驱动层的中间件技术。

      unitils来源于一个尝试,就是希望能以更务实的方式来看待单元测试......

      这个指南会告诉你,什么项目可以使用unitils。 并在这个指导方针页 中你可以了解到测试的准侧和它的特点。如果您想了解如何可以配置unitils ,并得以迅速地启动,请查看cookbook

  • unitils的断言
  • unitils的模块
  • 数据库的测试
  • 数据库的自动测试
  • hibernate的测试
  • jpa的测试
  • spring的测试
  • mock object的测试
  • 今后的方向

      unitils的断言

      在开始这个指南之前我们先说明一下独立于unitils核心模块的断言。在下面的例子中,不需要进行配置,将unitils的jar包和依赖包放在你的classpath下,就可以进行测试了。

      通过反射进行断言

      一个典型的单元测试包含了结果值和期望值的比较,unitils提供了断言的方法以帮助你进行该操作,让我们看看实例2中对有着id、first name、last name属性的User类的2个实例的比较

public class User {
    private long id;
    private String first;
    private String last;

    public User(long id, String first, String last) {
        this.id = id;
        this.first = first;
        this.last = last;
    }
}

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertEquals(user1, user2);
    你期望这个断言是成功的,因为这两个实例含有相同的属性,但是运行的结果并非如此,应为User类并没有覆写
equals()方法,所以assertEquals是对两个实例是否相等进行判断(user1 == user2)结果导致了比较的失败。
    假设你像如下代码一样实现了equals方法
public boolean equals(Object object) {
    if (object instanceof User) {
        return id == ((User) object).id;
    }
    return false;
}

       这在你的程序逻辑中是一个合乎逻辑的实现,当两个User实例拥有相同的id的时候,那么这两个实例就是相等的。然而这种方式在你的单元测试中并不合适,并不能通过id的相同来认为两个user是相同的。

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "Jane", "Smith");
assertEquals(user1, user2);

       这个断言将会成功,但这并不是你所期望的,因此不要使用assertEquals来对两个对象进行判定是否相等(外覆类和java.lang.String类除外)。要想断言他们相等,一种方法就是断言每个属性相等。

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertEquals(user1.getId(), user2.getId());
assertEquals(user1.getFirst(), user2.getFirst());
assertEquals(user1.getLast(), user2.getLast());

       unitils提供了一些方法来帮助你执行断言更加的简单,通过反射,使用ReflectionAssert.assertRefEquals上面的代码重写如下:

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertRefEquals(user1, user2);
   这个断言将通过反射对两个实例中的每个属性都进行比较,先是id、然后是first name、最后是last name。
   如果一个属性本身也是一个对象,那么将会使用反射进行递归比较,这同样适合与集合、map、和数组之间的比较,他们
的每个元素会通过反射进行比较。如果值是一个基本类型或者是一个外覆类,那么将会使用==进行值的比较,因此下面的断
言会取得成功
assertRefEquals(1, 1L); 

List<Double> myList = new ArrayList<Double>();
myList.add(1.0);
myList.add(2.0);
assertRefEquals(Arrays.asList(1, 2), myList);

      宽松的断言

     出于可维护性,这一点是十分重要的,举例说明:如果你要计算一个帐户的余额,那你就没比较检查这个帐户的名称。他只会增加复杂性,使之更难理解。如果你想让你的测试代码更容易生存,更容易重构的话,那请确保你断言的范围。

      宽松的顺序

      在比较集合和数组的时候你可能并不关心他们中元素的顺序,通过使用ReflectionAssert.assertRefEquals方法并配合ReflectionComparatorMode.LENIENT_ORDER参数将忽略元素的顺序。

List<Integer> myList = Arrays.asList(3, 2, 1);
assertRefEquals(Arrays.asList(1, 2, 3), myList, LENIENT_ORDER);
   无视默认
   第二种的从宽方式是使用ReflectionComparatorMode.IGNORE_DEFAULTS模式,当这种模式被设置的时候,java
的默认值,如null、0、false将会不参与断言(忽略)。
   举个例子,如果你有一个User类,该类有着first name,last name,street等属性,但是你仅仅想对first name
和street进行检查而忽略其他的属性。
User actualUser   = new User("John", "Doe", new Address("First street", "12", "Brussels"));
User expectedUser = new User("John",  null, new Address("First street", null,       null));
assertRefEquals(expectedUser, actualUser, IGNORE_DEFAULTS);

      你所期望忽略的属性的对象必须放在断言左边,如果放在右边那么依然进行比较。

assertRefEquals(null, anyObject, IGNORE_DEFAULTS);  // Succeeds
assertRefEquals(anyObject, null, IGNORE_DEFAULTS);  // Fails

      宽松的日期

      第三种从宽处理是ReflectionComparatorMode.LENIENT_DATES,当两个日期都是值,或者都是null的时候,实际的日期将会被忽略(即断言为相等)。

Date actualDate =   new Date(44444);
Date expectedDate = new Date();
assertRefEquals(expectedDate, actualDate, LENIENT_DATES);

      assertLenEquals

      ReflectionAssert还提供了一种断言,他提供宽松的顺序又提供无视的忽略。

List<Integer> myList = Arrays.asList(3, 2, 1);
assertLenEquals(Arrays.asList(1, 2, 3), myList); 

assertLenEquals(null, "any");  // Succeeds
assertLenEquals("any", null);  // Fails

      属性断言

      assertLenEqualsassertRefEquals都是比较对象,ReflectionAssert也提供方法对对象的属性进行比较。(依赖与ONGL)。

      一些属性比较的例子

assertPropertyLenEquals("id", 1, user);  //断言user的id属性的值是1 
assertPropertyLenEquals("address.street", "First street", user); //断言user的address的street属性

      在这个方式中你期望的值和判定的对象也可以使用集合

assertPropertyLenEquals("id", Arrays.asList(1, 2, 3), users);
assertPropertyLenEquals("address.street", Arrays.asList("First street", 
"Second street", "Third street"), users);
posted @ 2008-04-05 14:23 小小~咖啡豆 阅读(2299) | 评论 (5)编辑 收藏
  1. 写代码,就一定要写测试
  2. 不要受单元测试的教条所限
  3. 相信单元测试将会带来的成果
  4. 统一考虑编码和测试
  5. 测试比单元代码重要
  6. 测试的最佳时机是代码刚写完之时
  7. 测试不会白费
  8. 当天有瑕疵的测试也比后补的完美测试好
  9. 不好的测试也比没有测试强
  10. 测试有时可以验证意图
  11. 只有傻瓜不用工具
  12. 用好的去测试不好的

引至:Info中文网站http://www.infoq.com/cn/news/2007/04/savoia-tao-of-testing

posted @ 2007-04-30 09:59 小小~咖啡豆 阅读(381) | 评论 (0)编辑 收藏

實際運用 Tomcat 5.0.19,我們了解在不修改 Tomcat 原始碼的狀況下,使用者透過 Form submit 的資料將一律以 ISO8859-1 處理,程式設計師必須自行將字串將轉換為 Big5(繁體中文) or GB2312/GBK(簡體中文),我們在應用程式中,對所有的 request.getParameter("xx"); 作了 toBig5String() 的處理,理論上,所有的中文問題應該不會出現才對,結果,還是發現某些狀況下,中文還是變成亂碼!

經過分析整理,我們發現問題出在 QueryString 的解析,以前在 Tomcat 4.x 時代,無論 SUBMIT 時採用 GET or POST,Tomcat server 對 parameters 的處理都採用相同的編碼,但在 Tomcat 5.x 版,不知何故,卻將 QueryString 的解析獨立出來,目前確認,Form 的 Method 採用 GET 及直接將參數寫在 URL 上的中文,上傳到 Tomcat 時,無論如何轉碼,都會變成亂碼,那怕你事先作過 URLEncode 也一樣。

網站上,有人針對這個問題,建議將所有中文改採用 base64 編碼,到了 server 上,程式將自行土 base64 decode 回來,確保中文不會發生問題。這樣作法當然可以解決這個問題,但是所有網頁變成限定要採用 POST,且程式設計師要隨時分清楚,那個參數是採用 GET 上傳,那個參數是採用 POST 上傳,然後再針對不同的方式採用不同的解析,這樣的程式一點兒移植性都沒有,更別提跨平台、跨國際語言了。

研究 Tomcat 的文件及原始碼,我們找到了問題所在及解決的方法,只有按著以下的作法,才能使 Form submit 的資料完全按著 ISO8859-1 的編碼,當然,若是全照著 Tomcat 的文件說明去作,肯定還是不行,你還是得加上這個參數到 server.xml 中才行。

解決方案

請先研究 $TOMCAT_HOME/webapps/tomcat-docs/config/http.html 這個說明檔,擷錄重點如下:
URIEncoding:This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.

useBodyEncodingForURI:This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitely set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false.

上述二個 Tomcat 參數,是設定在 server.xml 中的 http <Connector /> 區塊,要解決 QueryString 中文變成亂碼的問題,你必須至少設定這二個參數其中之一。
URIEncoding 請設定為 URIEncoding="ISO-8859-1" 指定為 "ISO-8859-1" 編碼,讓 QueryString 的字元編碼與 post body 相同。
useBodyEncodingForURI 這是用來相容 Tomcat 4.x 版的,設定的值是 "true" or "false",意思是指 "要不要讓 QueryString 與 POST BODY 採用相同的字元編碼 ?",若是設成 true,那也可達到 "ISO-8859-1" 編碼的需求。
建議,採用 URIEncoding 的設定,畢竟 useBodyEncodingForURI 的作法是為了相容 Tomcat 4.X。不過若照原文的說明,理論上這二個參數都不設,Tomcat 也該採用 "ISO-8859-1" 的編碼,那為什麼還是會有問題呢 ? 我們由 Tomcat Source Code 來看就清楚了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 這一段碼是 Tomcat 用來解 QueryString 的程式,
// 在 org.apache.tomcat.util.http.Parameters 這個 class 裡。
private String urlDecode(ByteChunk bc, String enc)
  throws IOException {
  if( urlDec==null ) {
     urlDec=new UDecoder(); 
  }
  urlDec.convert(bc);
  String result = null;
  if (enc != null) {
    bc.setEncoding(enc);
    result = bc.toString();
  } 
  else {
    CharChunk cc = tmpNameC;
    cc.allocate(bc.getLength(), -1);
    // Default encoding: fast conversion
    byte[] bbuf = bc.getBuffer();
    char[] cbuf = cc.getBuffer();
    int start = bc.getStart();
    for (int i = 0; i < bc.getLength(); i++) {
      cbuf[i] = (char) (bbuf[i + start] & 0xff);
    }
    cc.setChars(cbuf, 0, bc.getLength());
    result = cc.toString();
    cc.recycle();
  }
  return result;
}

請特別注意紅色區塊,當 Tomcat 發現 QueryString 並沒有設定 encode 時,並非像文件中所說預設採用 ISO-8859-1 的編碼,而是用一段 fast conversion 來處理,才會造成中文問題,所以,還是必須在 Server.xml 中,加上 URLEncoding 的參數設定才行哦。

Connector 的設定範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Connector
debug="0"
acceptCount="100"
connectionTimeout="20000"
disableUploadTimeout="true"
port="80"
redirectPort="8443"
enableLookups="false"
minSpareThreads="25"
maxSpareThreads="75"
maxThreads="150"
maxPostSize="0"
URIEncoding="ISO-8859-1"
>
</Connector>

文章来至:http://www.javaworld.com.tw/jute/post/view?bid=9&id=44042&sty=1&tpg=1&age=0
posted @ 2007-04-26 10:33 小小~咖啡豆 阅读(7005) | 评论 (0)编辑 收藏

绝对的最强的java ide的7.0M1已经出了,快去试试把,
http://www.jetbrains.com/idea/nextversion/

posted @ 2007-04-12 09:07 小小~咖啡豆 阅读(271) | 评论 (0)编辑 收藏
仅列出标题  下一页