《Java Testing with Spock》_4写单元测试

4.1测试方法中的Spock结构

def "2加3可以得到5"() {
	//given块及其描述
    given: "两个整数,2和3"
	int a = 3
	int b = 2
    
	//when块及其描述
	when: "把他们相加"
	int result = a + b
    
	//then块及其描述
	then: "结果是5"
	result == 5
}

除了常用的given-when-then结构意外,Spock还提供了其他几个语义,如下图所示:
1.png

4.4 setup

def "装有一种产品的购物篮的重量跟产品相同(替代)"() {
    //准备单元测试。
	setup: "一个空购物篮和一台电视"
	Product tv = new Product(name:"bravia",price:1200,weight:18)
	Basket basket = new Basket()
    
    //触发将要测试的动作。
	when: "用户想购买电视"
	basket.addProduct(tv)
    
    //检查结果。
	then: "购物篮重量等于电视"
	basket.currentWeight == tv.weight
}

这里感觉和given没啥区别。

4.8 and

def "有三个产品的购物篮的重量是产品重量之和"() {
    //given块仅处理被测类。
	given: "一个空购物篮"
	Basket basket = new Basket()
    
    //and块创建协作者。
	and: "几种产品"
	Product tv = new Product(name:"bravia",price:1200,weight:18)
	Product camera = new Product(name:"panasonic",price:350,weight:2)
	Product hifi = new Product(name:"jvc",price:600,weight:5)
	
    when: "用户想购买电视,摄像机和高保真音响"
	basket.addProduct tv
	basket.addProduct camera
	basket.addProduct hifi
	
    then: "购物篮重量等于所有产品重量之和"
	basket.currentWeight == (tv.weight + camera.weight + hifi.weight)
}
def "有三个产品的购物篮的重量是产品重量之和(替代)"() {
	given: "一个空购物篮,一台电视,一台照相机和一个高保真音响"
	Basket basket = new Basket()
	Product tv = new Product(name:"bravia",price:1200,weight:18)
	Product camera = new Product(name:"panasonic",price:350,weight:2)
	Product hifi = new Product(name:"jvc",price:600,weight:5)
	
    //原始when块
    when: "用户想购买电视.."
	basket.addProduct tv
	
    //扩展when块
    and: "..相机.."
	basket.addProduct camera
	
    and: "..和wifi"
	basket.addProduct hifi
	
    then: "购物篮重量等于所有产品重量之和"
	basket.currentWeight == (tv.weight + camera.weight + hifi.weight)
}
def "装有三种产品的购物篮的重量和数量是正确的(有争议)"() {
	given: "一个空购物篮,一台电视,一台照相机和一个高保真音响"
	Basket basket = new Basket()
	Product tv = new Product(name:"bravia",price:1200,weight:18)
	Product camera = new Product(name:"panasonic",price:350,weight:2)
	Product hifi = new Product(name:"jvc",price:600,weight:5)
	
    when: "用户想购买电视,摄像机和高保真音响"
	basket.addProduct tv
	basket.addProduct camera
	basket.addProduct hifi
	
    //原始的when块
	then: "购物篮的重量等于所有产品的重量"
	basket.currentWeight == (tv.weight + camera.weight + hifi.weight)
	
    //扩展then块
	and: "它包含3个产品"
	basket.productTypesCount == 3
}

4.13 expect

def "有两个产品的购物篮的重量是产品重量之和(前提条件)"() {
	given: "一个空购物篮,一台电视和一台照相机"
	Product tv = new Product(name:"bravia",price:1200,weight:18)
	Product camera = new Product(name:"panasonic",price:350,weight:2)
	Basket basket = new Basket()
	
    //expect块执行中间断言
    expect:"里面什么也不要"
	basket.currentWeight == 0
	basket.productTypesCount == 0
	
    when: "用户想购买电视和相机"
	basket.addProduct tv
	basket.addProduct camera
	
    //then块检查最终结果
    then: "购物篮重量等于相机和电视"
	basket.currentWeight == (tv.weight + camera.weight)
}

4.14 cleanup

def "装有一种产品的购物篮的重量跟产品相同"() {
	given: "一个空购物篮和一台电视"
	Product tv = new Product(name:"bravia",price:1200,weight:18)
	Basket basket = new Basket()
	
    when: "用户想购买电视"
	basket.addProduct(tv)
	
    then: "购物篮重量等于电视"
	basket.currentWeight == tv.weight
	
    //cleanup块将始终运行,即使when失败
    cleanup: "刷新购物篮物品"
    //then块检查最终结果。
	basket.clearAllProducts()
}

4.21 Spock生命周期

class LifecycleSpec extends spock.lang.Specification{ 
		//初始化一个代价昂贵(耗资源)的对象
		def setupSpec() { 
           println "Will run only once"
    }    
    //所有测试的通用代码
    def setup() {
           println "Will run before EACH feature"
		} 
		//测试方法
    def "测试第一个功能"() {           
    			expect: "trivial test"
          println "first feature runs"           
          2 == 1 +1
		} 
		//测试方法
    def "测试第二个功能"() {           
    			 expect: "trivial test"
           println "second feature runs"           
           5 == 3 +2
    }    
    //所有测试的公共清理代码
    def cleanup() {
           println "Will run once after EACH feature"
    }    
    
    def cleanupSpec() {
           println "Will run once at the end"
		} 
} 

输出:

Will run only once
Will run before EACH feature
first feature runs
Will run once after EACH feature
Will run before EACH feature
second feature runs
Will run once after EACH feature
Will run once at the end

可见setupSpec和cleanupSpec只会执行一次,而setup和cleanup在每个测试方法前后都会执行。

4.22 @Shapred注解

class SharedSpec extends spock.lang.Specification{
  	
  	//只创建一次
    @Shared
    CreditCardProcessor creditCardProcessor;
    
    //会创建多次
    BillableBasket basket
    
    //初始化代价昂贵/速度慢的对象
    def setupSpec() {
				creditCardProcessor = new CreditCardProcessor()
		}
  	//共享对象可以正常使用
		def setup() {
  			basket = new BillableBasket()
        creditCardProcessor.newDayStarted()
        basket.setCreditCardProcessor(creditCardProcessor)
		}

		def "用户购买单一产品"() {
       	given: "一个购物车和一台电视机"
       	Product tv = new Product(name:"bravia",price:1200,weight:18)
        
        and: "用户想购买电视机" 
        basket.addProduct(tv)
          
				when: "用户登出" 
        basket.checkout()
          
				then: "获得收入即为电视价格" 
        creditCardProcessor.currentRevenue == tv.price
		}

		def "用户购买两样产品"() {
       	given: "一个购物车和一台相机"
       	Product camera = new Product(name:"panasonic",price:350,weight:2)
          
				and: "用户想购买两台相机" 
				basket.addProduct(camera,2)
          
				when: "用户登出" 
        basket.checkout()
          
				then: "取得收入为两种产品的价格"
        creditCardProcessor.currentRevenue == 2 * camera.price
		}
    
		//运行多次
  	def cleanup() { 
      	basket.clearAllProducts()
		}
  	//只运行一次
		def cleanupSpec() { 	
      	creditCardProcessor.shutDown()
		} 
}

可以使用@Shared注解,这样可以确保Spock仅创建一次。

4.30 使用闭包来进行判断

def "用Groovy闭包的普通测试"() {
   given: "一个装有产品的列表"
   List<String> products= ["camera", "laptop", "hifi"]
   
   expect: "相机应该是其中之一"
 	 products.any{ productName -> productName == "camera"}    //迭代列表并传递任何名为camera的值
    
   and: "热狗不应该在其中"
   products.every{ productName -> productName != "hotdog"}  //迭代列表并检查所有产品的名称
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值