Unitils教程.doc_第1页
Unitils教程.doc_第2页
Unitils教程.doc_第3页
Unitils教程.doc_第4页
Unitils教程.doc_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Unitils教程 单元测试应该很容易,直观.至少在理论上是这样的。 然而现实的项目通常跨越多个层次,有的是数据驱动有的使用中间件技术,比如EJB和Hibernate等等。 Unitils源于尝试更加务实的单元测试,它始于一套测试准则,并为了方便应用这些准则而开发了一个开源代码库。 本教程将通过一些实例向您展示如何在您的项目中使用Unitils。 断言应用 数据库测试 应用Spring测试 应用mock objects测试 应用EasyMock支持Assertion utilities 断言应用首先以断言的应用来开始我们的教程,Unitils 提供的断言是可以独立应用在核心模块里不依赖其他模块的部分,不需要配置只要加入jar包并加入到classpath 里就可以使用。应用反射的断言典型的单体测试一般都包含一个重要的组成部分:对比实际产生的结果和希望的结果是否一致的方法:断言方法(assertEquals)。Unitils为我们提供了一个非常实用的assertion方法,让我们用比较两个USER对象的实例(User包括id ,first name ,last name属性)来开始我们这一部分的介绍。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包含相同的属性,所以你一定以为断言是成功的。但是事实恰恰相反,断言失败,因为user类没有覆写equals()方法,所以断言就用判断两个对象是否相等来来返回结果,换句话说就是采用了user1 = user2的结果,用两个对象的引用是否一致作为判断的依据。假如你像下面这样重写equals方法,public boolean equals(Object object) if (object instanceof User) return id = (User) object).id; return false;也许通过判断两个USER的ID是否相等来判断这两个user是否相等在您的程序逻辑里是行得通的,但是在单体测试里未必是有意义的,因为判断两个user是否相等被简化成了user的id是否相等了。User user1 = new User(1, John, Doe);User user2 = new User(1, Jane, Smith);assertEquals(user1, user2);按照上面的代码逻辑,也许断言成功了,但是这是您期望的么?所以最好避免使用equals()方法来实现两个对象的比较(除非对象的属性都是基本类型)。对了,还有一个办法也许能够有效,那就是把对象的属性一个一个的比较。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.assertReflectionEquals方法,上面的代码可以重写如下:User user1 = new User(1, John, Doe);User user2 = new User(1, John, Doe);assertReflectionEquals(user1, user2);这种断言采用反射机制,循环的比较两个对象的filed的值,比如上面的例子,它就是依次对比id,first,last的值是否相等。如果某个filed本身就是object,那么断言会递归的依次比对这两个object的所有filed,对于Arrays ,Maps ,collection也是一样的,会通过反射机制递归的比较所有的element,如果值的类型是基本类型(int, long, .)或者基本类型的包装类(Integer, Long, .),就会比较值是否相等(using =)。看看下面的代码,这回断言成功了!assertReflectionEquals(1, 1L);List myList = new ArrayList();myList.add(1.0);myList.add(2.0);assertReflectionEquals(Arrays.asList(1, 2), myList);宽松式断言源于对代码可维护性的原因,只添加对测试有益的断言是十分重要的。让我用一个例子来说明这一点:假如一个计算account balance的测试代码,那么就没有对bank-customer的name进行断言的必要,因为这样就增加了测试代码的复杂度,让人难于理解,更重要的是当代码发生变化时增加了测试代码的脆弱性。为了让你的测试代码更容易的适应其他代码的重构,那么一定保证你的断言和测试数据是建立在测试范围之内的。为了帮助我们写出这样的测试代码,ReflectionAssert方法为我们提供了各种级别的宽松断言。下面我们依次介绍这些级别的宽松断言。顺序是宽松的:第一种宽松级别就是忽略collection 或者array中元素的顺序。其实我们在应用list的时候往往对元素的顺序是不关心的。比如:一个代码想要搜索出所有无效的银行账号,那么返回的结果的顺序就对我们业务逻辑没什么影响。为了实现这种宽松模式,ReflectionAssert.assertReflectionEquals方法可以通过配置来实现对顺序的忽略,只要ReflectionAssert.assertReflectionEquals方法设置ReflectionComparatorMode.LENIENT_ORDER参数就可以了。比如:List myList = Arrays.asList(3, 2, 1);assertReflectionEquals(Arrays.asList(1, 2, 3), myList, LENIENT_ORDER);忽略缺省值第二种宽松方式是:如果断言方法被设置为ReflectionComparatorMode.IGNORE_DEFAULTS模式的话,java 的default values比如 objects 是null 值是 0 或者 false, 那么断言忽略这些值的比较,换句话说就是断言只会比较那些你初始化了的期望值,如果你没有初始化一些filed,那么断言就不会去比较它们。还是拿个例子说明比较好,假设有一个user类:有first name, last name, street. field属性,但是你只想比较两个对象实例的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);assertReflectionEquals(expectedUser, actualUser, IGNORE_DEFAULTS);你想忽略的属性值设置为null那么一定把它放到左边参数位置(=expected),如果只有右边参数的值为null,那么断言仍然会比较的。assertReflectionEquals(null, anyObject, IGNORE_DEFAULTS); / SucceedsassertReflectionEquals(anyObject, null, IGNORE_DEFAULTS); / Fails宽松的date第三种宽松模式是ReflectionComparatorMode.LENIENT_DATES,这种模式只会比较两个实例的date是不是都被设置了值或者都为null, 而忽略date的值是否相等,如果你想严格比较对象的每一个域,而又不想去比较时间的值是不是相等,那么这种模式就是合适你的。Date actualDate = new Date(44444);Date expectedDate = new Date();assertReflectionEquals(expectedDate, actualDate, LENIENT_DATES);assertLenientEquals方法ReflectionAssert类为我们提供了具有两种宽松模式的断言:既忽略顺序又忽略缺省值的断言assertLenientEquals,使用这种断言上面两个例子就可以简化如下了:List myList = Arrays.asList(3, 2, 1);assertLenientEquals(Arrays.asList(1, 2, 3), myList);assertLenientEquals(null, any); / SucceedsassertLenientEquals(any, null); / FailsassertReflection .以这种方式命名的断言是默认严格模式但是可以手动设置宽松模式的断言,assertLenient .以这种方式命名的断言是具有忽略顺序和忽略缺省值的断言。属性断言assertLenientEquals和 assertReflectionEquals这两个方法是把对象作为整体进行比较,ReflectionAssert类还给我们提供了只比较对象的特定属性的方法:assertPropertyLenientEquals 和 assertPropertyReflectionEquals,比如:assertPropertyLenientEquals(id, 1, user);assertPropertyLenientEquals(address.street, First street, user);这个方法的参数也支持集合对象,下面的例子就会比较特定的属性的集合中的每一个元素是否相等。assertPropertyLenientEquals(id, Arrays.asList(1, 2, 3), users);assertPropertyLenientEquals(address.street, Arrays.asList(First street, Second street, Third street), users);同样每一种方法都提供两个版本,assertPropertyReflection Equals 和assertPropertyLenient Equals . assertPropertyReflection.以这种方式命名的断言是默认严格模式但是可以手动设置宽松模式的断言,assertPropertyLenient.以这种方式命名的断言是具有忽略顺序和忽略缺省值的断言。数据库测试对于商业应用程序来说数据库层的单体测试是十分重要的,但是却常常被放弃了,因为太复杂了。Unitils大大减少了这种复杂度而且可维护。下面就介绍支持DatabaseModule 和DbUnitModule的数据库测试。通过DbUnit来管理测试数据数据库测试运行在一个单体测试数据库上,它提供完整且易于管理的测试数据,DbUnitModule在Dbunit的基础上提供对测试数据集的支持。加载测试数据集还是让我们以一个简单的例子开始,findByName方法通过first和last name抽取一个User。典型的单体测试代码如下:DataSetpublic class UserDAOTest extends UnitilsJUnit4 Test public void testFindByName() User result = userDao.findByName(doe, john); assertPropertyLenientEquals(userName, jdoe, result); Test public void testFindByMinimalAge() List result = userDao.findByMinimalAge(18); assertPropertyLenientEquals(firstName, Arrays.asList(jack), result); 在测试代码中加入DataSet标签,Unitils就会为测试代码找测试需要的DbUnit数据文件。如果没有指定文件名,Unitils会自动在测试类目录下查找以className .xml格式命名的测试数据集文件。数据集文件将采用DbUnits FlatXMLDataSet文件格式并包含测试需要的所有数据。表中的所有数据集的内容首先将被删除,然后所有数据集中的数据将被插入到表中,数据集里没有的表将不会被清空,如果你想清空指定的表,可以在数据集文件里添加一个空的表元素,比如在数据集文件里添加,如果你想指定为一个null值,你可以用【null】设置。比如以UserDAOTest为例,建立一个类级的数据集文件,以UserDAOTest.xml命名,然后放到UserDAOTest相同目录下: 首先会清空usergroup和user的表内容,然后把数据集文件的内容插入到usergroup和user里,名字为smith的user的first name被设置为null。假设testFindByMinimalAge()方法需要一个特殊的测试数据集而不是类级的测试数据集,那么我们建立一个名字为UserDAOTest.testFindByMinimalAge.xml的数据集文件并放到测试类的目录下。 然后在方法前加入DataSet标签,就会重写默认的数据集文件。public class UserDAOTest extends UnitilsJUnit4 Test DataSet(UserDAOTest.testFindByMinimalAge.xml) public void testFindByMinimalAge() List result = userDao.findByMinimalAge(18); assertPropertyLenientEquals(firstName, Arrays.asList(jack), result); 方法级的数据集不能被重用,因为越多的数据集文件就意味着更多的维护。开始你也许会重用类级的数据集,绝大多数的情况下一个小的数据集会在很多测试中被重用,但是如果这样的话,就会出现一个非常大的而且数据相关性很小的数据集,也许每个方法单独使用一个数据集会好些,或者把一个测试拆分为几个测试。DataSet(UserDAOTest_general.xml, ConfigSettings.xml)public class UserDAOTest extends UnitilsJUnit4 Test public void testFindByName() User result = userDao.findByName(doe, john); assertPropertyLenientEquals(userName, jdoe, result); Test DataSet(UserDAOTest_ages.xml) public void testFindByMinimalAge() List result = userDao.findByMinimalAge(18); assertPropertyLenientEquals(firstName, Arrays.asList(jack), result); 配置数据集加载策略默认的数据集加载到数据库里采用clean insert策略,也就是先把数据库中的数据clean,然后把数据集的数据insert到数据库。详细的过程是:数据集里有的表都会在数据库中清空,然后把数据集里的测试数据插入到表中。这种行为是可以被配置的,通过修改属性DbUnitModule.DataSet.loadStrategy.default可以实现。比如我们修改如下属性:DbUnitModule.DataSet.loadStrategy.default=org.unitils.dbunit.datasetloadstrategy.InsertLoadStrategy这种策略是用insert 代替 clean insert,也就是数据集里的表在数据库里不被删除而只是把数据集里的测试数据插入到数据库中。这种加载策略也可以在特点的测试用例上使用,通过修改DataSet标签的属性值。DataSet(loadStrategy = InsertLoadStrategy.class)因为这个和DbUnit是类似的,采用不同的加载策略就是使用不同的数据库操作。下面的加载策略是默认支持的。 CleanInsertLoadStrategy:数据集里有的表在数据库中都要把数据删掉,然后把数据集里的数据插入到数据库中。 InsertLoadStrategy:就是简单的把数据集里的数据插入到数据库中。 RefreshLoadStrategy:用数据集里的数据更新数据库中的数据。也就是:数据集里有数据库也有的数据被更新,数据集里有而数据库里没有的数据被插入,数据库里面有而数据集里没有的数据保持不变。 UpdateLoadStrategy:用数据集里的数据更新数据库里的数据,如果数据集里的数据不在数据库中那么失败(比如一条数据拥有相同的主键值)。证实测试结果在测试运行完之后用数据集中的数据去检查数据库中的数据,有时候这是非常有用的。比如你想检查大块数据更新和一个存储过程的执行结果是否正确。下面的例子是测试一个把所有一年没有使用的账户废除掉的方法。public class UserDAOTest extends UnitilsJUnit4 Test ExpectedDataSet public void testInactivateOldAccounts() userDao.inactivateOldAccounts(); 注意我们在测试方法上面加了一个ExpectedDataSet标签,它会告诉Unitils去找一个叫做UserDAOTest.testInactivateOldAccounts-result.xml数据集文件,并且去比较数据集里的数据和数据库中的数据。 对于这个数据集它会去检查数据库的表中是否有和这两条数据相同的数据记录。和DataSet标签一样,文件名可以被指定,如果没有指定文件名就会采用下面的命名规则:className .methodName -result.xml。使用的数据集尽量最小化,增加数据量也就意味着更多的维护。作为一种变通,你可以在不同的测试中采用相同的检查数据。使用multi-schema数据集一些应用不止连接到一个数据库schema。为了实现这个,Unitils扩展了数据集XML定义,使它包含多个schema的数据。下面的例子就是从两种不同的schema中为数据库加载数据。 在这个例子中,我们定义了两个schema: SCHEMA_A 和 SCHEMA_B。第一个schema, SCHEMA_A 与默认的XML命名空间相连,第二个schema: SCHEMA_B与命名空间b相连,如果一个表的xml元素以命名空间b为前缀,那么希望的表在schema: SCHEMA_B里,如果没有命名空间前缀就认为是schema: SCHEMA_A。在这个例子中测试数据定义为tables SCHEMA_A.user 和SCHEMA_B.role 。如果没有指定默认的命名空间,就把database.schemaNames中的第一个schema作为默认命名空间。假设定义了以下的schema names:database.schemaNames=SCHEMA_A, SCHEMA_B这就让SCHEMA_A作为默认的schema,你也可以简化上面的数据集的例子,把默认命名空间的定义移除。 连接到测试数据库在上面的例子里面我们留下了一个重要的问题没有提及:我们测试数据库用到数据源来自哪里,并且我们怎么让我们测试的类来使用我们的数据源。当我们开始我们的测试实例的时候,Unitils会根据我们定义的属性来创建一个数据源实例连接到我们的测试数据库。随后的数据库测试会重用相同的数据源实例。建立连接的细节定义在下面的属性里:database.driverClassName=oracle.jdbc.driver.OracleDriverdatabase.url=jdbc:oracle:thin:yourmachine:1521:YOUR_DBdatabase.userName=johndatabase.password=secretdatabase.schemaNames=test_john我们在工程的perties文件里设置driver和 url这两个属性,这是为整个工程使用的属性,如果特定用户使用的属性我们可以设置在perties文件里,比如user, password 和 schema,这样每个开发者就使用自己定义的测试数据库的schema,而且彼此之间也不回产生影响。在一个测试被建立之前,数据源要注入到测试实例中:如果在一个属性或者setter方法前发现TestDataSource标签就会设置或者调用数据源实例。你必须为你的测试代码加上配置代码,好让你的测试类使用数据源,一般的都通过继承一个基类实现数据库测试,下面就是一个典型基类的代码:public abstract class BaseDAOTest extends UnitilsJUnit4 TestDataSource private DataSource dataSource; Before public void initializeDao() BaseDAO dao = getDaoUnderTest(); dao.setDataSource(dataSource); protected abstract BaseDAO getDaoUnderTest();上面的例子是用一个标签来获得数据源的引用,调用DatabaseUnitils.getDataSource()方法也可以达到相同的目的。事物(Transactions)由于不同的原因,数据库的事物处理对于测试代码是十分重要的,下面就是一些重要的原因: 数据库操作只有在事物处理的情况下才运行,比如:SELECT FOR UPDATE or triggers that execute ON COMMIT。 很多工程的测试代码在运行之前需要填充一些数据来达到测试的目的,在测试过程中数据库中的数据会被插入或者修改,为了在每一次测试前数据库都在一个特定的状态下,我们测试之前开始一个事物,测试之后回滚到起始状态。 如果你的项目应用Hibernate或者JPA,那么这些框架都要在一个事物下测试才能够保证系统运行正常。默认情况下每一次测试都执行一个事物,在测试结束的时候commit。这种默认情况可以通过修改属性来改变,比如:DatabaseModule.Transactional.value.default=disabled这个属性的其他合法设置值可以是:commit, rollback 和 disabled。事物的行为也可以通过加入Transactional标签在测试类级别修改。比如:Transactional(TransactionMode.ROLLBACK)public class UserDaoTest extends UnitilsJUnit4 这样的话,在每一次测试结束后都会回滚,Transactional这个标签是可继承的,所以可以在公共父类里定义,而不是在每个类里单独定义。其实Unitils是依靠Spring来进行事物管理的,但是这并不意味着你必须在你的代码里加入Spring来进行事物管理,事实上是使用了Spring进行事物管理但是这一切都是透明的。如果使用unitils对Spring的支持,可以在Spring的配置文件里设置一个PlatformTransactionManager类型的Bean ,unitils就会用它做事物管理器。应用Spring测试Unitils提供了一些在Spring框架下进行单体测试的特性。Spring的一个基本特性就是:类要设计成为:没有Spring容器或者在其他容器下仍然易于进行单体测试。但是很多时候在Spring容器下进行测试还是非常有用的。Unitils提供了以下支持Spring的特性: ApplicationContext配置的管理 在单体测试代码中注入Spring的Beans 使用定义在Spring配置文件里的Hibernate SessionFactory 引用在Spring配置中Unitils 数据源ApplicationContext配置可以简单的在一个类,方法或者属性上加上SpringApplicationContext标签,并用Spring的配置文件作为参数,来加载应用程序上下文。下面就是一个例子:public class UserServiceTest extends UnitilsJUnit4 SpringApplicationContext(spring-config.xml, spring-test-config.xml) private ApplicationContext applicationContext; 加载spring-config.xml 和 spring-test-config.xml这两个配置文件来生成一个应用程序上下文并注入到加注解的域范围里,在setter方法加注解一样可以达到注入应用程序上下文的目的。加载应用程序上下文的过程是:首先扫描父类的SpringApplicationContext标签,如果找到了就在加载子类的配置文件之前加载父类的配置文件,这样就可以让子类重写配置文件和加载特定配置文件。比如:SpringApplicationContext(spring-beans.xml)public class BaseServiceTest extends UnitilsJUnit4 public class UserServiceTest extends BaseServiceTest SpringApplicationContext(extra-spring-beans.xml) private ApplicationContext applicationContext; 上面的例子创建了一个新的应用程序上下文,它首先加载spring-beans.xml配置文件,然后加载extra-spring-beans.xml配置文件,这个应用程序上下文会注入到加入标签的属性里。注意上面的例子,创建了一个新的应用程序上下文,这么做是因为要为这个类加载指定的配置文件。Unitils会尽可能的重用应用程序上下文,比如下面的例子没有加载新的配置文件,所以就重用相同的实例。SpringApplicationContext(spring-beans.xml)public class BaseServiceTest extends UnitilsJUnit4 public class UserServiceTest extends BaseServiceTest SpringApplicationContext private ApplicationContext applicationContext; public class UserGroupServiceTest extends BaseServiceTest SpringApplicationContext private ApplicationContext applicationContext; 在父类BaseServiceTest里指定了配置文件,应用程序上下文会创建一次,然后在子类UserServiceTest 和 UserGroupServiceTest里会重用这个应用程序上下文。因为加载应用程序上下文是一个非常繁重的操作,如果重用这个应用程序上下文会大大提升测试代码的性能。注入Spring的Beans只要配置好了应用程序上下文,所有以SpringBean , SpringBeanByType 或者SpringBeanByName注释的fields / setters都会注入beans,下面的例子展示了如何根据应用程序上下文来获得UserService bean实例。SpringBean(userService)private UserService userService;SpringBeanByNameprivate UserService userService;SpringBeanByTypeprivate UserService userService;用SpringBean标签你可以从应用程序上下文得到一个具有独一无二名字的Spring的bean, SpringBeanByName这个标签效果相同,只是它根据类field名称来区分bean。当使用SpringBeanByType标签的时候,应用程序上下文会查找一个和filed类型相同的bean,这个例子中,会查找UserService类或者子类的bean,如果这样的bean不存在或者不只找到一个结果,那么抛出异常。在setter上面也可以使用相同的标签,比如:SpringBeanByTypepublic void setUserService(UserService userService) this.userService = userService;应用Mock(模拟)对象进行测试单体测试是要把测试代码隔离开的,Mock objects可以让你测试一块代码而不用在意这块代码所依赖的objects 和 services。到了unitils2.0版本,它提供了一套完整的动态生成mock objects的解决方案,并支持mock的创建和注入。在unitils2.0版本之前,是使用EasyMock框架的,你也许会问为什么已经有像EasyMock这样强大的Mock 对象应用库,unitils还要写一个完整的Mock模块呢?一个重要的原因就是它想提供一个大大改进的并且用户友好性更强的库。Mock测试实例下面是测试alert service的实例:sendScheduledAlerts()方法需要从AlertSchedulerService获取所有的scheduled alerts,然后把它们传递给MessageSenderService。public class AlertServiceTest extends UnitilsJUnit4 AlertService alertService; Message alert1, alert2; List alerts; Mock mockSchedulerService; Mock mockMessageService; Before public void init() alertService = new AlertService(mockSchedulerService.getMock(), mockMessageService.getMock(); alert1 = new Alert(.); alert2 = new Alert(.); alerts = Arrays.asList(alert1, alert2); Test public void testSendScheduledAlerts() mockSchedulerService.returns(alerts).getScheduledAlerts(null); alertService.sendScheduledAlerts(); mockMessageService.assertInvoked().sendMessage(alert1); mockMessageService.assertInvoked().sendMessage(alert2); 这个测试实例使用SchedulerService 和 MessageService的mock(模拟)。在测试代码的第一个语句中: mockSchedulerService.returns(alerts).getScheduledAlerts(null);首先指定接下来调用SchedulerService mock对象的getScheduledAlerts方法时将返回包括alert1和alert2的List对象alerts,而且getScheduledAlerts方法的参数是任意的(因为设置行为的参数是Null就意味着任意值)。接下来的测试代码调用这个方法:alertService.sendScheduledAlerts();然后调用断言语言,检查在mockMessageService对象里的sendAlert方法是不是以alert1和alert2为参数被调用了。mock objects实例化mock objects被包装到一个control 对象里,这个control对象可以定义行为并调用断言语句,在你的测试代码里声明一个mock作为属性,而不必特意去实例化它。Mock mockService;Unitils会创建mock control对象并在测试之前分配到域属性里,为了获得mock control对象本身,只要调用control对象的getMock()方法。如下:MyService myService = mockService.getMock(); 定义Mock行为动作Unitils提供了简单明了的定义mock行为动作的语法,以myUser 为参数调用getScheduledAlerts 方法返回alerts ,我们可以简单的定义如下:mockSchedulerService.returns(alerts).getScheduledAlerts(myUser);还可以定义抛出的异常:mockSchedulerService.raises(new BackEndNotAvailableException().getScheduledAlerts(myUser);你也可以像下面这样指定异常类:mockSchedulerService.raises(BackEndNotAvailableException.class).getScheduledAlerts(myUser);你也可以向下面这样指定用户行为:mockSchedulerService.performs(new MockBehavior() public Object execute(ProxyInvocation mockInvocation) / . (retrieve alerts logic) return alerts; );如果相同的方法要在不同的调用中执行不同的行为,那么你就必须在定义行为时通过调用onceReturns , onceRaises 或者 oncePerforms让它只适用一次。比如:mockSchedulerService.onceReturns(alerts).getScheduledAlerts(myUser);mockSchedulerService.onceRaises(new BackEndNotAvailableException().getScheduledAlerts(myUser);如果你用 returns 和 raises 代替 onceReturns 和onceRaises,那么第二次定义的行为永远也不会被调用(这种情况下,永远调用第一次定义的行为)。由于可维护性的原因,我们尽量不使用once这个语法,因为假想的方法调用顺序使你的测试代码变得脆弱。如果可能可以使用调用相同的函数使用不同参数的办法来解决上面的问题。验证期望的调用测试方法执行完之后,往往我们想查看mock objects的一些我们期望的方法是不是被调用了。比如:mockMessageService.assertInvoked().sendMessage(alert1);这个方法验证了mock MessageService 中的sentMessage方法是否被调用,并

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论