小何自助建站,商务网站创建经费预算,做非法网站会怎样,建设网站公司需要哪些证件存根类 测试代码 java介绍 我遇到的一件事是使用模拟框架的团队假设他们在模拟。 他们并不知道Mocks只是Gerard Meszaros在xunitpatterns.com上分类的“测试双打”之一。 重要的是要认识到每种类型的双重测试在测试中扮演着不同的角色。 用与学习不同模式或重构相同的方式您需要了解每种类型的测试double的原始角色。 然后可以将它们组合起来以满足您的测试需求。 我将简要介绍这种分类的产生方式以及每种类型的不同之处。 我将在Mockito中使用一些简短的简单示例进行此操作。 一段简短的历史 多年来人们一直在编写系统组件的轻量级版本以帮助进行测试。 通常这被称为存根。 在2000年的文章“ Endo-Testing使用模拟对象进行单元测试”中介绍了模拟对象的概念。 从那时起Meszaros将StubMocks和许多其他类型的测试对象归类为Double Double。 该术语已由Martin Fowler在“ Mocks Are nt Stubs”中引用并在Microsoft社区中被采用如“ Exploring The Test Doubles Continuum of Test Doubles”中所示。 参考部分中显示了这些重要论文的链接。 考试双打的类别 上图显示了常用的双重测试类型。 以下URL提供了对每个模式及其功能以及替代术语的很好的交叉引用。 http://xunitpatterns.com/Test%20Double.html 莫基托 Mockito是一个测试间谍框架学习起来非常简单。 Mockito值得注意的是在测试之前没有定义任何模拟对象的期望因为它们有时在其他模拟框架中也是如此。 开始嘲笑时这会导致更自然的样式IMHO。 以下示例在这里纯粹是为了简单演示如何使用Mockito实施不同类型的测试双打。 网站上有大量有关如何使用Mockito的特定示例。 http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html 使用Mockito测试双打 以下是一些使用Mockito的基本示例以显示Meszaros定义的每个测试双打的作用。 我为每个对象都提供了指向主要定义的链接因此您可以获得更多示例和完整定义。 虚拟对象 http://xunitpatterns.com/Dummy%20Object.html 这是所有测试双打中最简单的一次。 这是一个没有实现的对象仅用于填充与测试无关的方法调用的参数。 例如下面的代码使用大量代码来创建客户这对测试并不重要。 只要客户数恢复为1该测试就不会在乎添加哪个客户。 public Customer createDummyCustomer() {County county new County(Essex);City city new City(Romford, county);Address address new Address(1234 Bank Street, city);Customer customer new Customer(john, dobie, address);return customer;
}Test
public void addCustomerTest() {Customer dummy createDummyCustomer();AddressBook addressBook new AddressBook();addressBook.addCustomer(dummy);assertEquals(1, addressBook.getNumberOfCustomers());
} 我们实际上并不关心客户对象的内容但是它是必需的。 我们可以尝试使用null值但是如果代码正确则可能会引发某种异常。 Test(expectedException.class)
public void addNullCustomerTest() {Customer dummy null;AddressBook addressBook new AddressBook();addressBook.addCustomer(dummy);
} 为了避免这种情况我们可以使用一个简单的Mockito假人来获得所需的行为。 Test
public void addCustomerWithDummyTest() {Customer dummy mock(Customer.class);AddressBook addressBook new AddressBook();addressBook.addCustomer(dummy);Assert.assertEquals(1, addressBook.getNumberOfCustomers());
} 正是这个简单的代码创建了一个要传递给调用的虚拟对象。 Customer dummy mock(Customer.class); 不要被模拟语法所迷惑-这里扮演的角色是虚拟的而不是模拟的。 区别在于测试双重性的作用而不是用于创建双重性的语法。 该类可以轻松替代客户类并使测试非常容易阅读。 测试存根 http://xunitpatterns.com/Test%20Stub.html 测试存根的作用是将受控值返回到要测试的对象。 这些被描述为测试的间接输入。 希望有一个例子可以阐明这意味着什么。 采取以下代码 public class SimplePricingService implements PricingService
{ PricingRepository repository;public SimplePricingService(PricingRepository pricingRepository) {this.repository pricingRepository;}Overridepublic Price priceTrade(Trade trade) {return repository.getPriceForTrade(trade);}Overridepublic Price getTotalPriceForTrades(Collectiontrades) {Price totalPrice new Price();for (Trade trade : trades){Price tradePrice repository.getPriceForTrade(trade);totalPrice totalPrice.add(tradePrice);}return totalPrice;} SimplePricingService具有一个协作对象即交易存储库。 交易存储库通过getPriceForTrade方法将交易价格提供给定价服务。 为了测试SimplePricingService中的业务逻辑我们需要控制这些间接输入 即我们从未通过测试的输入。 如下所示。 在下面的示例中我们对PricingRepository存根以返回可用于测试SimpleTradeService的业务逻辑的已知值。 Test
public void testGetHighestPricedTrade() throws Exception {Price price1 new Price(10); Price price2 new Price(15);Price price3 new Price(25);PricingRepository pricingRepository mock(PricingRepository.class);when(pricingRepository.getPriceForTrade(any(Trade.class))).thenReturn(price1, price2, price3);PricingService service new SimplePricingService(pricingRepository);Price highestPrice service.getHighestPricedTrade(getTrades());assertEquals(price3.getAmount(), highestPrice.getAmount());
} 破坏者的例子 测试存根有2个常见的变体响应者和破坏者。 如前面的示例使用响应者来测试快乐路径。 破坏者用于测试以下异常行为。 Test(expectedTradeNotFoundException.class)
public void testInvalidTrade() throws Exception {Trade trade new FixtureHelper().getTrade();TradeRepository tradeRepository mock(TradeRepository.class);when(tradeRepository.getTradeById(anyLong())).thenThrow(new TradeNotFoundException());TradingService tradingService new SimpleTradingService(tradeRepository);tradingService.getTradeById(trade.getId());
} 模拟对象 http://xunitpatterns.com/Mock%20Object.html 模拟对象用于在测试期间验证对象行为。 通过对象行为我的意思是我们检查在运行测试时是否在对象上执行了正确的方法和路径。 这与存根的支持作用完全不同存根用于为您正在测试的任何结果提供结果。 在存根中我们使用为方法定义返回值的模式。 when(customer.getSurname()).thenReturn(surname); 在模拟中我们使用以下形式检查对象的行为。 verify(listMock).add(s); 这是一个简单的示例我们要测试是否正确审核了新交易。 这是主要代码。 public class SimpleTradingService implements TradingService{TradeRepository tradeRepository;AuditService auditService;public SimpleTradingService(TradeRepository tradeRepository, AuditService auditService){this.tradeRepository tradeRepository;this.auditService auditService;}public Long createTrade(Trade trade) throws CreateTradeException {Long id tradeRepository.createTrade(trade);auditService.logNewTrade(trade);return id;
} 下面的测试为贸易存储库创建存根并为AuditService创建模拟 然后我们在模拟的AuditService上调用verify以确保TradeService调用了 logNewTrade方法正确 Mock
TradeRepository tradeRepository;Mock
AuditService auditService;Test
public void testAuditLogEntryMadeForNewTrade() throws Exception { Trade trade new Trade(Ref 1, Description 1);when(tradeRepository.createTrade(trade)).thenReturn(anyLong()); TradingService tradingService new SimpleTradingService(tradeRepository, auditService);tradingService.createTrade(trade);verify(auditService).logNewTrade(trade);
} 以下行对模拟的AuditService进行检查。 verify(auditService).logNewTrade(trade); 该测试使我们能够证明审计服务在创建交易时的行为正确。 测试间谍 http://xunitpatterns.com/Test%20Spy.html 值得一看上面的链接以严格定义测试间谍。 但是在Mockito中我喜欢使用它来包装实际对象然后验证或修改它的行为以支持您的测试。 这是我们检查列表的标准行为的示例。 注意我们既可以验证是否调用了add方法也可以断言该项目已添加到列表中。 Spy
List listSpy new ArrayList();Test
public void testSpyReturnsRealValues() throws Exception {String s dobie;listSpy.add(new String(s));verify(listSpy).add(s);assertEquals(1, listSpy.size());
} 将其与仅可验证方法调用的模拟对象进行比较。 因为我们仅模拟列表的行为所以它不记录已添加项目并且在调用size方法时返回默认值零。 Mock
ListlistMock new ArrayList();Test
public void testMockReturnsZero() throws Exception {String s dobie;listMock.add(new String(s));verify(listMock).add(s);assertEquals(0, listMock.size());
} testSpy的另一个有用功能是能够对返回调用进行存根。 完成此操作后该对象将表现正常直到调用存根方法为止。 在此示例中我们将get方法存根以始终引发RuntimeException。 其余行为保持不变。 Test(expectedRuntimeException.class)
public void testSpyReturnsStubbedValues() throws Exception {listSpy.add(new String(dobie)); assertEquals(1, listSpy.size());when(listSpy.get(anyInt())).thenThrow(new RuntimeException());listSpy.get(0);
} 在此示例中我们再次保留了核心行为但更改了size方法以初始返回1并为所有后续调用返回5。 public void testSpyReturnsStubbedValues2() throws Exception {int size 5;when(listSpy.size()).thenReturn(1, size);int mockedListSize listSpy.size();assertEquals(1, mockedListSize);mockedListSize listSpy.size();assertEquals(5, mockedListSize); mockedListSize listSpy.size();assertEquals(5, mockedListSize);
} 这真是不可思议 假物件 http://xunitpatterns.com/Fake%20Object.html 假物品通常是手工制作或重量较轻的物品仅用于测试不适合生产。 一个很好的例子是内存数据库或伪造的服务层。 它们往往提供比标准测试双打更多的功能因此通常不适合使用Mockito进行实现。 这并不是说它们不能像这样构造只是可能不值得采用这种方式来实现。 参考“ 小事半解 ” – 敏捷工程技术博客上来自JCG合作伙伴 John Dobie的Mockito了解测试双打 。 翻译自: https://www.javacodegeeks.com/2012/05/mocks-and-stubs-understanding-test.html存根类 测试代码 java