在过去,我会经常向你展示 EasyMock 是什么和怎样使用它测试你的Java应用。基于这个目的,我将创建一个简单的股票程序并使用 JUnit 和 EasyMock 库测试。
在开始之前,让我们先理解一下使用 EasyMock 的需求。加入,你在创建一个Android 移动应用用来获取用户股票档案。你的应用需要使用股票市场服务从正式服务器来检索股票价格(例如纳斯达克)。
当你开始测试代码的时候,你也许不会想要去使用真实股票市场服务器来获取股票价格。相反,你也许希望来些虚拟价格数据。所以你需要模拟股票市场服务然后返回虚拟数据,而不去访问真实服务器。
EasyMock 就是用来干这事的 -- 帮你模拟接口。你可以预定义一些模拟对象的行为,然后在测试代码时使用模拟这些对象。因为你关心的是测试你的代码逻辑而不是外在服务和对象。因此。
为了使之清晰,请看一下下面的代码摘要:
1 | StockMarket marketMock = EasyMock.createMock(StockMarket. class ); |
2 | EasyMock.expect(marketMock.getPrice( "EBAY" )).andReturn( 42.00 ); |
3 | EasyMock.replay(marketMock); |
第一行,我们要求 EasyMock 创建一个服务于 StockMarket 接口的模拟对象。然后第二行,我们定义了这个虚拟对象的行为--例如当getPrice()对象被调用并传递 “EBAY” 参数时,模拟对象将返回 42.00 .然后我们调用 replay() 方法时,将使模拟对象备用。
这样就差不错关联好了 EasyMock 的上下文了和它的基本使用。接下来将深入我们的证劵应用。
注意:点击此处下载 Github 上的源码
证卷应用
我们的证券应用非常简单。有一个 Stock 类来存储股票名和数量,Portfolio 类来保存股票列表。Portfolio 类有一个方法用来计算证券的总价格。我们的类用 StockMarket 对象来检索股票价格。当测试我们的代码时,我们将使用 EasyMock 来模拟StockMarket。
Stock.java
01 | package com.veerasundar.easymock; |
08 | public Stock(String name, int quantity) { |
10 | this .quantity = quantity; |
13 | public String getName() { |
17 | public void setName(String name) { |
21 | public int getQuantity() { |
25 | public void setQuantity( int quantity) { |
26 | this .quantity = quantity; |
StockMarket.java
用来模拟股票市场服务的接口。它包含一个通过给定股票名返回价格的方法。
1 | package com.veerasundar.easymock; |
3 | public interface StockMarket { |
4 | public Double getPrice(String stockName); |
Portfolio.java
该对象包含了 Stock 对象列表和一个计算证券总价格的方法。它使用 StockMarket 对象来检索股票价格。但是硬编码依赖不是好的实践,我们不应该在此就初始化 stockMarket 对象,我们应该在使用测试代码的时候注入进来。
01 | package com.veerasundar.easymock; |
03 | import java.util.ArrayList; |
06 | public class Portfolio { |
09 | private StockMarket stockMarket; |
11 | private List<Stock> stocks = new ArrayList<Stock>(); |
17 | public Double getTotalValue() { |
19 | for (Stock stock : this .stocks) { |
20 | value += (stockMarket.getPrice(stock.getName()) * stock |
26 | public String getName() { |
30 | public void setName(String name) { |
34 | public List<Stock> getStocks() { |
38 | public void setStocks(List<Stock> stocks) { |
42 | public void addStock(Stock stock) { |
46 | public StockMarket getStockMarket() { |
50 | public void setStockMarket(StockMarket stockMarket) { |
51 | this .stockMarket = stockMarket; |
至此,我们便完成了整个应用的编码,接下来我们将测试 Portfolio.getTotalValue() 方法,因为那是我们的业务逻辑所在。
用 JUnit 与 EasyMock 测试 Portfolio 应用
PortfolioTest.java
01 | package com.veerasundar.easymock.tests; |
03 | import junit.framework.TestCase; |
05 | import org.easymock.EasyMock; |
06 | import org.junit.Before; |
09 | import com.veerasundar.easymock.Portfolio; |
10 | import com.veerasundar.easymock.Stock; |
11 | import com.veerasundar.easymock.StockMarket; |
13 | public class PortfolioTest extends TestCase { |
15 | private Portfolio portfolio; |
16 | private StockMarket marketMock; |
20 | portfolio = new Portfolio(); |
21 | portfolio.setName( "Veera's portfolio." ); |
22 | marketMock = EasyMock.createMock(StockMarket. class ); |
23 | portfolio.setStockMarket(marketMock); |
26 | <a href= "http://my.oschina.net/test45" target= "_blank" rel= "nofollow" > @Test </a> |
27 | public void testGetTotalValue() { |
34 | Stock ebayStock = new Stock( "EBAY" , 2 ); |
35 | portfolio.addStock(ebayStock); |
36 | assertEquals( 84.00 , portfolio.getTotalValue()); |
正如你所看到的,在 setUp() 调用时我们创建新的 Portfolio 对象。然后我们调用 EasyMock 要求为 StockMarket 接口创建一个模拟对象。然后我们使用 Portfolio.setStockMarket() 方法将这个对象注入到 Portfolio 对象。
在 @Tes t方法,我们使用以下代码定义模拟对象的行为:
1 | EasyMock.expect(marketMock.getPrice( "EBAY" )).andReturn( 42.00 ); |
2 | EasyMock.replay(marketMock); |
这样一来,当 getPrice() 方法带有 “EBAY” 的参数被调用的时候,将会返回42.00。
然后我们创建了一个数量为2的 ebayStock 股票,并将其添加到我们的 Portfolio 中。将我们设置 EBAY 价格为 42.00 时,我们便知道股票的总价格为 84.00(2*42.00)。在最后一行,我们使用 assertEquals() 进行了同样的声明。
如果 getTotalValue() 中代码不出错的话,以上测试应该会成功,否则测试将会失败。
结论
以上便是如果使用 EasyMock 库模拟外部服务/对象以及在测试代码中使用的示例,EasyMock 能做的远不止我在上面展示的,点击这里了解更多关于 EasyMock 的信息。
原文链接 / OSChina.NET 原创翻译
|