• [置顶] EasyMock构建单元测试


    1. 背景

    单元测试作为程序的基本保障。很多时候构建测试场景是一件令人头疼的事。因为之前的单元测试都是内部代码引用的,环境自给自足。开发到了一定程度,你不得不到开始调用外部的接口来完成你的功能。而外部条件是不稳定的。你为了模拟外部环境要创建各种文件、各种数据。严重影响到单元测试的效率。EasyMock应运而生,他提供了模拟的接口和类。不用费神去构建各种烦人的环境,就能开展有效的测试。

    2. 准备环境

    Easymock 3.2 + JUnit 4.11

    3. 构建测试

    a) 实际场景

    i. 你负责开发一个会计师的功能。但计算个人所得税的接口由外部提供(鬼知道项目经理是怎么想的)。

    ii. 你的代码已经开发完成了。负责开发个人所得税的接口的同事老婆生了四胞胎,天天请假带孩子。接口没写完。

    iii. 你要完成你的代码并提交测试用例。前提你个懒鬼,半点额外工作都不想做。同事老婆生孩子又不能去催。然后你在网上找到了EasyMock.......

    b) 测试代码

    i. 个人所得税的接口

    /**
     * Copyright © 2008-2013, WheatMark, All Rights Reserved
     */
    package com.fitweber.wheat.interfaces;
    
    /**
     * 计算个人所得税
     * @author wheatmark hajima11@163.com 
     * @Blog http://blog.csdn.net/super2007
     * @version 1.00.00
     * @project wheatMock
     * @file com.fitweber.wheat.interfaces.IPersonalIncomeTax.java
     * @bulidDate 2013-9-1
     * @modifyDate 2013-9-1
     * <pre>
     *    修改记录
     *    修改后版本:     修改人:  修改日期:     修改内容: 
     * </pre>
     */
    public interface IPersonalIncomeTax {
    	/**
    	 * 计算个人所得税,国内,2013年7级税率
    	 * @param income
    	 * @param deductedBeforeTax
    	 * @return
    	 */
    	public double calculate(double income,double deductedBeforeTax);
    
    }
    

    ii. 会计师类中计算工资方法

    /**
     * Copyright © 2008-2013, WheatMark, All Rights Reserved
     */
    package com.fitweber.wheat;
    
    import com.fitweber.wheat.interfaces.IPersonalIncomeTax;
    
    /**
     * 会计师类
     * @author wheatmark hajima11@163.com 
     * @Blog http://blog.csdn.net/super2007
     * @version 1.00.00
     * @project wheatMock
     * @file com.fitweber.wheat.Accountant.java
     * @bulidDate 2013-9-1
     * @modifyDate 2013-9-1
     * <pre>
     *    修改记录
     *    修改后版本:     修改人:  修改日期:     修改内容: 
     * </pre>
     */
    public class Accountant {
    	
    	private IPersonalIncomeTax personalIncomeTax;
    	
    	public Accountant(){
    		
    	}
    	
    	public double calculateSalary(double income){
    		//税前扣除,五险一金中个人扣除的项目。8%的养老保险,2%的医疗保险,1%的失业保险,8%的住房公积金
    		double deductedBeforeTax = income*(0.08+0.02+0.01+0.08);
    		return income - deductedBeforeTax - personalIncomeTax.calculate(income,deductedBeforeTax);
    	}
    
    	/**
    	 * @return the personalIncomeTax
    	 */
    	public IPersonalIncomeTax getPersonalIncomeTax() {
    		return personalIncomeTax;
    	}
    
    	/**
    	 * @param personalIncomeTax the personalIncomeTax to set
    	 */
    	public void setPersonalIncomeTax(IPersonalIncomeTax personalIncomeTax) {
    		this.personalIncomeTax = personalIncomeTax;
    	}
    	
    }
    

    iii. 测试会计师类中计算工资方法

    或许你不知道个人所得税的计算方式。但是你可以去百度一下。对,百度上有个人所得税计算器。和2011年出台的个人所得税阶梯税率。




    通过百度的帮忙(更多的时候你要求助于业务组的同事)你可以确认如果你同事的个人所得税的计算接口正确的话,传入国内实际收入8000.00,税前扣除1520.00。应该返回193.00的扣税额。然后我们可以设置我们的Mock对象的行为来模仿接口的传入和返回。用断言来确认会计师的计算工资的逻辑。完成了我们的测试用例。

    /**
     * Copyright © 2008-2013, WheatMark, All Rights Reserved
     */
    package com.fitweber.wheat.test;
    
    import static org.easymock.EasyMock.*;
    import junit.framework.Assert;
    
    import org.easymock.IMocksControl;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.fitweber.wheat.Accountant;
    import com.fitweber.wheat.interfaces.IPersonalIncomeTax;
    
    /**
     * 会计师测试类
     * @author wheatmark hajima11@163.com 
     * @Blog http://blog.csdn.net/super2007
     * @version 1.00.00
     * @project wheatMock
     * @file com.fitweber.wheat.test.AccountantTest.java
     * @bulidDate 2013-9-1
     * @modifyDate 2013-9-1
     * <pre>
     *    修改记录
     *    修改后版本:     修改人:  修改日期:     修改内容: 
     * </pre>
     */
    public class AccountantTest {
    
    	private IPersonalIncomeTax personalIncomeTax;
    	private Accountant accountant;
    	
    	/**
    	 * @throws java.lang.Exception
    	 */
    	@Before
    	public void setUp() throws Exception {
    		IMocksControl control = createControl();
    		personalIncomeTax = control.createMock(IPersonalIncomeTax.class);
    		accountant = new Accountant();
    		accountant.setPersonalIncomeTax(personalIncomeTax);
    	}
    
    	/**
    	 * @throws java.lang.Exception
    	 */
    	@After
    	public void tearDown() throws Exception {
    		System.out.println("----------AccountantTest中的全部用例测试完毕---------");
    	}
    	
    	@Test
    	public void testCalculateSalary(){
    		//个人所得税的计算接口还没实现,但会计师的计算工资的方法已经写好了。需要测试。
    		//我们可以先Mock一个出来测试。
    		//个人所得税的计算接口正确的话,传入实际收入8000.00,税前扣除1520.00。应该返回193.00.
    		expect(personalIncomeTax.calculate(8000.00,1520.00)).andReturn(193.00);
    		//设置到回放状态
    		replay(personalIncomeTax);
    		//验证计算工资方法计算是否正确。
    		Assert.assertEquals(8000.00-1520.00-193.00, accountant.calculateSalary(8000.00));
    		verify(personalIncomeTax);
    	}
    	
    	
    	
    }
    


    4. 执行测试

    最后是最简单的一步了。右键点击AccountantTest.javaRun As > JUnit Test。得到下面的成功界面。


    PS:到上面一步,单元测试已经是完成了。拥有好奇心的你还可以testCalculateSalary()方法里的数值去看看如果单元测试不通过会报什么错。

    比如,改一下所传的参数personalIncomeTax.calculate(8000.00,1520.00)变为personalIncomeTax.calculate(9000.00,1520.00)。

    改一下断言什么的,报错又会是什么。Assert.assertEquals(8000.00-1520.00-193.00, accountant.calculateSalary(8000.00));

    具体的EasyMock文档在网络上已经漫天飞。自己去找找,深入了解下EasyMock

  • 相关阅读:
    slua
    Lua和.Net
    Python Embedded
    vtk
    CMAKE使用
    Create instance from class name string
    SLN & PROJ
    Python/C API
    魔兽世界编年史卷一
    PyCharm注册码
  • 原文地址:https://www.cnblogs.com/pangblog/p/3297028.html
Copyright © 2020-2023  润新知