C/C++教程

JUnit+EasyMock测试实例

本文主要是介绍JUnit+EasyMock测试实例,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

JUnit+EasyMock测试实例

一、实例一(纯Java)

要求:

编写一个简单的货币基金选择器,考虑以下几种货币类型:CNY(人民币)、USD(美元)、GBP(英镑)、EUR(欧元)、CAD(加元),假设基金选择方法每次选择兑换值最高的货币作为投资目标,实验包括对JUnit和EasyMock的使用,最后给出关键的代码截图和测试用例运行结果。

1.1 接口 ExchangeRate

import java.io.IOException;

public interface ExchangeRate {
    public double getRate(String inputCurrency, String outputCurrency) throws IOException;
}

1.2 需测试类 Currency.java

import java.io.IOException;

public class Currency {
    private String unit;
    private long amount;
    private int cents;

    public Currency(double amount,String unit){
        this.unit=unit;
        setAmount(amount);
    }
    public void setAmount(double amount2) {
        this.amount = new Double(amount2).longValue();
        this.cents=(int) amount2*100%100;
    }

    public Currency toChange(ExchangeRate converter){
        String[]u={"CNY","USD","GBP","EUR","CAD"};
        String changeUnit=null;
        double maxRate=0;
        double temp;
        try{
            for(String tempUnit:u){
                temp=converter.getRate(this.unit,tempUnit);
                if(temp>maxRate) {
                    changeUnit=tempUnit;
                    maxRate=temp;
                }
            }
            if(changeUnit.equals(this.unit)) return this;
            double input = amount+cents/100.0;
            return new Currency(input*maxRate,changeUnit);
        }catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public boolean equals(Object o){
        if(o instanceof Currency){
            Currency other =(Currency) o;
            return this.unit.equals(other.unit) && this.amount==other.amount && this.cents==other.cents;
        }
        return false;
    }
 
    public String toString(){
        return this.amount+"."+cents+" "+unit;
    }
}

1.3 测试类

import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.junit.Test;

import java.io.IOException;

public class CurrencyTest extends TestCase {

    @Test
    public void test() throws IOException {
        Currency testObject=new Currency(2.5,"USD");
        Currency expected=new Currency(3.75,"EUR");

        ExchangeRate mockRate= EasyMock.createMock(ExchangeRate.class);
        EasyMock.expect(mockRate.getRate("USD","USD")).andReturn(1.0);
        EasyMock.expect(mockRate.getRate("USD","CNY")).andReturn(0.5);
        EasyMock.expect(mockRate.getRate("USD","GBP")).andReturn(1.1);
        EasyMock.expect(mockRate.getRate("USD","EUR")).andReturn(1.5);
        EasyMock.expect(mockRate.getRate("USD","CAD")).andReturn(0.3);
        EasyMock.replay(mockRate);

        Currency actual=testObject.toChange(mockRate);
        assertEquals(actual,expected);
    }
}

{% note warning %}

  1. Currency类中要覆盖Object的toString方法,是因为assertEquals方法中传入的是两个Currency对象,它会像根据Object的toString方法,将二者转化为String类型,再通过equals方法比较。默认转化为Currency对象的地址。
  2. Currency类中要覆盖Object的equals方法,是因为Object的equals方法默认按地址比较,而不是内容。

{% endnote %}


二、实例二 (模拟JavaEE环境)

2.1 需测试类 LoginServlet.java

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class LoginServlet extends HttpServlet {
	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		if("admin".equals(username) && "123456".equals(password)) {
			ServletContext context = getServletContext();
			RequestDispatcher dispatcher = context.getNamedDispatcher("dispatcher");
			dispatcher.forward(req, res);
		}else {
			throw new RuntimeException("Login failed.");
		}
	}
}

2.2 测试类 TestLoginServlet.java

import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

public class TestLoginServlet extends TestCase {
    private HttpServletRequest request;
    private ServletContext context;
    private RequestDispatcher dispatcher;
    private LoginServlet loginServlet;

    @Before
    public void setUp() throws Exception {
        request= EasyMock.createMock(HttpServletRequest.class);
        context=EasyMock.createMock(ServletContext.class);
        dispatcher=EasyMock.createMock(RequestDispatcher.class);
        loginServlet=new LoginServlet();
    }

    @Test
    public void testLoginSuccess() throws Exception{
        EasyMock.expect(request.getParameter("username")).andReturn("admin");
        EasyMock.expect(request.getParameter("password")).andReturn("123456");
        EasyMock.expect(context.getNamedDispatcher("dispatcher")).andReturn(dispatcher);
        dispatcher.forward(request,null);
        EasyMock.replay(request);
        EasyMock.replay(context);
        EasyMock.replay(dispatcher);
        //匿名类 
        loginServlet =new LoginServlet(){
          public ServletContext getServletContext(){
              return context;
          }
        };
        loginServlet.doPost(request,null);
        EasyMock.verify(request);
        EasyMock.verify(context);
        EasyMock.verify(dispatcher);
    }

    @Test
    public void testLoginFailed1() {
        EasyMock.expect(request.getParameter("username")).andReturn("ad");
        EasyMock.expect(request.getParameter("password")).andReturn("123456");
        EasyMock.replay(request);
        try {
            loginServlet.doPost(request,null);
        } catch (Exception e) {
            assertEquals("Login failed.",e.getMessage());
        }
        EasyMock.verify(request);
    }

    @Test
    public void testLoginFailed2() {
        EasyMock.expect(request.getParameter("username")).andReturn("admin");
        EasyMock.expect(request.getParameter("password")).andReturn("123");
        EasyMock.replay(request);
        try {
            loginServlet.doPost(request,null);
        } catch (Exception e) {
            assertEquals("Login failed.",e.getMessage());
        }
        EasyMock.verify(request);
    }
    @Test
    public void testLoginFailed3() {
        EasyMock.expect(request.getParameter("username")).andReturn(null);
        EasyMock.expect(request.getParameter("password")).andReturn("123456");
        EasyMock.replay(request);
        try {
            loginServlet.doPost(request,null);
        } catch (Exception e) {
            assertEquals("Login failed.",e.getMessage());
        }
        EasyMock.verify(request);
    }

    @Test
    public void testLoginFailed4() {
        EasyMock.expect(request.getParameter("username")).andReturn("admin");
        EasyMock.expect(request.getParameter("password")).andReturn(null);
        EasyMock.replay(request);
        try {
            loginServlet.doPost(request,null);
        } catch (Exception e) {
            assertEquals("Login failed.",e.getMessage());
        }
        EasyMock.verify(request);
    }
}

{% note warning %}

测试类中之所以用到匿名类,是因为要测试的代码中使用了getServletContext()方法,此方法是Servlet上下文的方法,此处模拟了环境,也应模拟此方法。

How使用匿名类?Java的匿名内部类

{% endnote %}


三、实例三

3.1 接口 DBUtility.java

package org.easymock.demo.domain;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public interface DBUtility {
    public abstract Connection getConnection();
	public abstract void closeDBResource(Connection conn);
	public abstract void closeDBResource(Statement stmt);
	public abstract void closeDBResource(ResultSet rs);
}

3.2 SalesOrders.java

package org.easymock.demo.domain;

import java.sql.ResultSet;
import java.sql.SQLException;
public interface SalesOrder {
	public String getOrderNumber();
    public String getRegion();
	public double getTotalPrice();
	public void setOrderNumber(String orderNumber);
	public void setRegion(String region);
	public void setTotalPrice(double totalPrice);
	
	public void loadDataFromDB(ResultSet resultSet) throws SQLException;
	public String getPriceLevel();
	public String toString();
}

3.3 SalesOrderImpl.java

package org.easymock.demo.domain;

import java.sql.ResultSet;
import java.sql.SQLException;

public class SalesOrderImpl implements SalesOrder {	
	private String orderNumber;
	private String region;
	private double totalPrice;

	public String getOrderNumber(){return orderNumber;}
	public String getRegion(){return region;}
	public double getTotalPrice(){return totalPrice;}
	public void setOrderNumber(String orderNumber){this.orderNumber = orderNumber;}
	public void setRegion(String region){this.region = region;}
	public void setTotalPrice(double totalPrice){this.totalPrice = totalPrice;}
  
	public void loadDataFromDB(ResultSet resultSet) throws SQLException {
		orderNumber = resultSet.getString(1);
		region = resultSet.getString(2);
		totalPrice = resultSet.getDouble(3);
	}

	public String getPriceLevel() {
		double totalPrice = this.getTotalPrice();
		double totalPoints = 0.0;
		
		if ("Africa".equalsIgnoreCase(this.getRegion()))
			totalPoints = totalPrice;
		else if ("Asia Pacific".equalsIgnoreCase(this.getRegion()))
			totalPoints = totalPrice * 0.9;
		else if ("Europe".equalsIgnoreCase(this.getRegion()))
			totalPoints = totalPrice * 0.85;
		else if ("America".equalsIgnoreCase(this.getRegion()))
			totalPoints = totalPrice * 0.8;
		else
			totalPoints = totalPrice * 0.75;
		
		if (totalPoints < 500)
			return "Level_A";
		else if (totalPoints < 1000)
			return "Level_B";
		else if (totalPoints < 2000)
			return "Level_C";
		else if (totalPoints < 4000)
			return "Level_D";
		else
			return "Level_E";
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("orderNumber = "+orderNumber+"\n");
		sb.append("region = "+region+"\n");
		sb.append("totalPrice = "+totalPrice+"\n");
		sb.append("priceLevel = "+this.getPriceLevel()+"\n");
		return sb.toString();
	}
}

3.4 测试 SalesOrderTestCase.java

package org.easymock.demo.testcase;

import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.demo.matcher.SQLEquals.sqlEquals;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.easymock.demo.domain.DBUtility;
import org.easymock.demo.domain.SalesOrder;
import org.easymock.demo.domain.SalesOrderImpl;

public class SalesOrderTestCase extends TestCase {
	public void testSalesOrder() {
		IMocksControl control = EasyMock.createControl();
		
		DBUtility mockDBUtility = control.createMock(DBUtility.class);
		Connection mockConnection = control.createMock(Connection.class);
		Statement mockStatement = control.createMock(Statement.class);
		ResultSet mockResultSet = control.createMock(ResultSet.class);

		try {
			mockDBUtility.getConnection();
			EasyMock.expectLastCall().andStubReturn(mockConnection);

			mockConnection.createStatement();
			expectLastCall().andStubReturn(mockStatement);

			mockStatement.executeQuery(sqlEquals("SELECT * FROM sales_order_table"));
			expectLastCall().andStubReturn(mockResultSet);

			mockResultSet.next();
			expectLastCall().andReturn(true).times(3);
			expectLastCall().andReturn(false).times(1);

			mockResultSet.getString(1);
			expectLastCall().andReturn("DEMO_ORDER_001").times(1);
			expectLastCall().andReturn("DEMO_ORDER_002").times(1);
			expectLastCall().andReturn("DEMO_ORDER_003").times(1);

			mockResultSet.getString(2);
			expectLastCall().andReturn("Asia Pacific").times(1);
			expectLastCall().andReturn("Europe").times(1);
			expectLastCall().andReturn("America").times(1);

			mockResultSet.getDouble(3);
			expectLastCall().andReturn(350.0).times(1);
			expectLastCall().andReturn(1350.0).times(1);
			expectLastCall().andReturn(5350.0).times(1);

			control.replay();
			
			Connection conn = mockDBUtility.getConnection();
			Statement stat = conn.createStatement();
			ResultSet rs = stat.executeQuery("select * from sales_order_table");

			int i = 0;
			String[] priceLevels = { "Level_A", "Level_C", "Level_E" };
			while (rs.next()) {
				SalesOrder order = new SalesOrderImpl();
				order.loadDataFromDB(rs);
				assertEquals(order.getPriceLevel(), priceLevels[i]);
				i++;
			}		
			control.verify();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

3.5 自定义参数匹配器 SQLEquals.java

package org.easymock.demo.matcher;

import static org.easymock.EasyMock.reportMatcher;
import org.easymock.IArgumentMatcher;

public class SQLEquals implements IArgumentMatcher {
	private String expectedSQL = null;
	public SQLEquals(String expectedSQL) {
		this.expectedSQL = expectedSQL;
	}

	public void appendTo(StringBuffer buffer) {
		buffer.append("SQLEquals(\"" + expectedSQL + "\")");
	}

	public boolean matches(Object actualSQL) {
		if (actualSQL == null && expectedSQL == null) return true;
		else if (actualSQL instanceof String) return expectedSQL.equalsIgnoreCase((String) actualSQL);
		else return false;
	}
	
	public static String sqlEquals(String in) {
        reportMatcher(new SQLEquals(in));
        return in;
    } 
}


四、参考文献

Java的匿名内部类

这篇关于JUnit+EasyMock测试实例的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!