Junit入门到掌握-22-JUnit扩展-测试桩Stub

这篇来学习单元测试中的Stub,翻译过来就是测试桩。测试过程中为什么要打桩,什么是桩,如何写一个简单的测试桩的例子,本篇就来了解这些基本的问题。

1.什么是测试桩

不要去看网上看哪些所谓的定义,在了解桩之前,我们需要了解依赖。

上面这个图,SUT表示被测试的软件,TestCode是我们写的一个测试用例,其中我们需要测试里面一个模块,但是这个模块依赖别的模块,依赖的模块加入是被部门甚至别公司开发,目前还没做好。为了不影响我们单元测试,我们认为这个依赖模块是没有问题的,然后我们自己写一个桩模块来代替这个依赖模块,这样测试用例就能继续执行下去。

所以桩就是模拟依赖模块的一段测试代码或者一个测试模块,一般我们单独写一个类,这个类以实现依赖模块或者接口。我们桩里面实现代码就随便返回一个数据,可以乱写返回数据,这都是可以。

 

2.代码准备

还是这个前面一篇用到标准工程

打开TrackingService.java文件,对addProtein(int amount)方法进行修改代码。

    public void addProtein(int amount){
	    total += amount;
	    history.add(new HistoryItem(historyId++, amount,"add", total));
	    
	    if(total > goal) {
	    	boolean sendResult = notifier.send("goal met");
	    	String historyMessage = "send: goal met";
	    	if(!sendResult) {
	    		historyMessage = "send_error: goal met";
	    	}
	    	history.add(new HistoryItem(historyId++, 0, historyMessage, total));
	    }
	}

if判断这段就是我们准备好的依赖代码,Notifier这个是一个接口,里面有一个具体的send方法由于各种原因没有准备好。这个Notifier就是我们依赖模块,目前由于没有send的具体实现,我们无法测试这段代码。

这个文件完整的代码

package com.anthony.protein;

import java.util.ArrayList;
import java.util.List;

public class TrackingService {
	
	private int total;
	private int goal;
	private List<HistoryItem> history = new ArrayList<HistoryItem>();
	private int historyId = 0;
	private Notifier notifier;
	

	public void addProtein(int amount){
	    total += amount;
	    history.add(new HistoryItem(historyId++, amount,"add", total));
	    
	    if(total > goal) {
	    	boolean sendResult = notifier.send("goal met");
	    	String historyMessage = "send: goal met";
	    	if(!sendResult) {
	    		historyMessage = "send_error: goal met";
	    	}
	    	history.add(new HistoryItem(historyId++, 0, historyMessage, total));
	    }
	}

	public void removeProtein(int amount){
	    total -= amount;
	    if(total < 1){
	        total = 0;
	    }
	    history.add(new HistoryItem(historyId++, amount,"subtract", total));
	}
	
	public int getTotal(){
	    return total;
	}

	public void setGoal(int value) throws InvalidGoalException{
		if(value < 0) {
			throw new InvalidGoalException();
		}
	    goal = value;
	}

	public boolean isGoalMet(){
	    return total >= goal;
	}

	public List<HistoryItem> getHistory(){
	    return history;
	}

}

依赖模块接口设计好了,但是没有具体实现方法

package com.anthony.protein;

public interface Notifier {

	boolean send(String message);
	
}

下面我们需要通过创建测试桩来继续我们的单元测试

 

3.创建测试桩

测试桩一般是依赖模块的名称加上Stub.java来命名,所以我创建这么一个类,并实现Notifier接口。

package com.anthony.protein;

public class NotifierStub implements Notifier {

	public boolean send(String message) {
		return true;
	}

}

这个测试桩里面我们随便写一个符合业务的返回值,我们业务上这个返回值要求是布尔值。这里我就是写一个True好了。

然后给TrackingSerivce.java添加一个带notifier参数的构造方法

    public TrackingService(Notifier notifier) {
		this.notifier = notifier;
	}

如果我们之前写的TracingServiceTest.java中的代码,由于刚才新的构造函数添加而出现报错,这里我们修改下TrackingService初始化的代码,加上这个参数,改成下面这样。

        @Before
	public void setup() {
		System.out.println("Before Method");
		ts = new TrackingService(new NotifierStub());
	}

 

4.写一个单元测试用例

在TrackingServiceTest.java添加下面测试用例,来测试我们桩代码。

        @Test
	public void whenGoalIsMetHistoryIsUpdate() throws InvalidGoalException {
		ts.setGoal(5);
		ts.addProtein(6);
		// 这种条件触发了Notifier 发送消息功能
		HistoryItem result = ts.getHistory().get(1); //取第二个数据
		assertEquals("send: goal met", result.getOperation());
	}

由于我们在NotifierStub.java中返回是true, 所以这里断言就用“send: goal met”, 如果返回false,你这里就改成“send_error: goal met”, 运行一下就能通过。

总结:为了方便测试不被打断,我们有时候需要写桩代码,桩代码返回值只要符合业务就可以,里面代码基本上都是假代码。利用写好的桩代码去跳过原本依赖的业务方法,这个就是单元测试中的桩模块测试。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值