StrutsTestCase配置的常見問題及其多級Action的處理方式
一:寫本文的原因
StrusTestCase是比較常見使用的測試方法,網上的教程很多。但是為什麼要寫這篇文章呢?首先網上的教程版本就2-3種,基本大家都互相copy,而且教程比較陳舊。第二,遇到的不少問題網上的很多人都沒給出可用的解決方法。下文會給出自己遇到的一些問題和具體的解決方法。
二:StrutsTestCase的基本原理
這裡簡單介紹一下StrutsTestCase的基本原理。StrutsTestCase是Junit的擴充類,主要用于對MVC工程的測試。下面的教程用于純Struts2工程。StrutsTestCase是一個用于測試Struts行為的基于Junit的測試架構。如果你使用Struts,那麼你會注意到它可以提供給你一種容易而有效的方式來測試你的應用程式的Struts行為類。說的明白一點就是用來測試一個具體的Action,同時自己模拟來自網頁的輸入資訊,然後運作一下測試類的excute,得到的結果的和你期望的值進行對比用來測試你的項目有沒有問題。至于更加詳細的原理大家可以百度找一些資料,本文的重點不在這裡。
三:StrutsTestCase的常見問題
其實這裡才是寫本文的目的所在,這裡分享幾個我遇到的幾個比較坑的問題。 第一個問題就是我引入了struts2-Junit-Plugin和一些Spring的一些jar包,發現各種類找不到,也就是未發現jar包,可我明明引入了jar包了啊?經過一段時間終于發現了問題的所在,原來我工程的struts2的核心jar包有問題。在那個版本的struts2的jar包發現了StrutsTestCase這個類,但是這個類裡面沒有任何函數。但是eclipse提醒我們引入類時預設的是struts2核心jar裡面提供的StrutsTestCase類。我也很納悶為何原本提供了這個接口但是不提供相應的測試函數呢?好吧,這時我們隻好重新換struts2的核心包了。筆者用的是最新版本的核心包,這個版本是沒有這個問題的:http://struts.apache.org/download.cgi#struts23163,下載下傳App即可,把裡面的struts2-blank.war解壓,把裡面的jar全部導入即可。這是第一個問題。 第二個問題又來了,當時筆者不放心把lib下的jar包全部導入了,結果報錯找不到包。這個原因是struts2的包一些自身就是高版本不支援低版本。那麼我們究竟需要哪些jar包呢?下面筆者把截圖發上。注意,經親測這裡的jar包是缺一不可的。

四:一個簡單的測試用例
好了,煩心的配置之後我們就開始愉快的測試吧。 筆者測試了一個圖書管理系統,下面先給出一個簡單的用例讓我們熟悉一下StrutsTestCase。之後我會在下一節給出一個比較棘手的問題。 這裡我要示範的是一個通過作者姓名查詢。為了突出核心問題,這裡把bean裡面的類就不貼了。要說明的是通過作者名做一些搜尋工作,然後把該作者的全部書籍存到list,把list共享一下在背景取得并列印。下面的代碼就模拟如何擷取這個list。 QueryAction:
package com.amaker.action;
import org.apache.struts2.ServletActionContext;
import java.util.List;
public class QueryAction{
private String Author;//the author's name
private String Tip;
public String execute()throws Exception{
OperaDB db = new OperaDB();
List<Book> list = db.Search(Author);
if(list == null || list.isEmpty()){
this.setTip("作者名錯誤或不存在,請重新輸入!");
return "error";
}else{
ServletActionContext.getRequest().getSession().setAttribute("List",list);
ServletActionContext.getRequest().setAttribute("list",list);
return "success";
}
}
//getter and setter
public String getTip() {
return Tip;
}
public void setTip(String tip) {
Tip = tip;
}
public void setAuthor(String author) {
Author = author;
}
}
QueryActionTest:
package com.amaker.action;
import java.util.List;
import org.apache.struts2.StrutsTestCase;
import com.opensymphony.xwork2.ActionProxy;
public class QueryActionTest extends StrutsTestCase{
public void testSuccessQuery() {
request.setParameter("Author","Margaret Mitchell");
ActionProxy proxy = getActionProxy("/query");
try {
proxy.execute();
List results = (List)request.getAttribute("list");
Book bk = (Book)results.get(0);
assertEquals(bk.getTitle(),"Gone with the Wind");
} catch (Exception e) {
e.printStackTrace();
}
}
public void testFailQuery() {
request.setParameter("Author"," ");
ActionProxy proxy = getActionProxy("/query");
QueryAction action = (QueryAction) proxy.getAction();
try {
proxy.execute();
assertEquals(action.getTip(),"作者名錯誤或不存在,請重新輸入!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
可以看到我們測試成功了。
五:關于多級Action的測試方法
我們可以看到StrutsTestCase的特點了,這裡是模拟單個網頁的請求來測試某個Action,但是如果該網頁還連接配接到其他網頁或者還有其他二級響應該怎麼辦呢?因為要測試一個Action不能利用上部的結果,因為這種測試是靜态的。那麼怎麼辦呢?有兩種思路:其一是再次人工模拟上次的結果在共享一下,二級響應再擷取。當然這種方法當資料量比較大時不靠譜。第二種思路就是我們在測試二級Action時先模拟一級Action,下面以一個例子說明: 這個例子就是上個步驟顯示出來書籍之後點選該書籍可以跳轉到另一個頁面顯示該書籍的詳細資訊。 index.java
package com.amaker.action;
import java.util.List;
import org.apache.struts2.ServletActionContext;
public class Index {
//the content to display
private String index;
private String ISBN;
private String Title;
private String Publisher;
private String PublisherDate;
private String Price;
private String Name;
private String Age;
private String Country;
private int AuthorID;
public String execute() throws Exception{
if(index==null)
index=ServletActionContext.getRequest().getSession().getAttribute("index").toString();
int num=Integer.parseInt(index);
ServletActionContext.getRequest().getSession().setAttribute("index",index);
@SuppressWarnings("unchecked")
List<Book> list = (List<Book>) ServletActionContext.getRequest().getSession().getAttribute("List");
Book bk = list.get(num);
this.setAge(bk.getAge());
this.setTitle(bk.getTitle());
this.setAuthorID(bk.getAuthorID());
this.setCountry(bk.getCountry());
this.setISBN(bk.getISBN());
this.setName(bk.getName());
this.setPrice(bk.getPrice());
this.setPublisherDate(bk.getPublisherDate());
this.setPublisher(bk.getPublisher());
return "success";
}
//setter and getter
public void setIndex(String index) {
this.index = index;
}
public void setAuthorID(int authorID) {
AuthorID = authorID;
}
public void setISBN(String iSBN) {
ISBN = iSBN;
}
public void setTitle(String title) {
Title = title;
}
public void setPublisher(String publisher) {
Publisher = publisher;
}
public void setPublisherDate(String publisherDate) {
PublisherDate = publisherDate;
}
public void setPrice(String price) {
Price = price;
}
public void setName(String name) {
Name = name;
}
public void setAge(String age) {
Age = age;
}
public void setCountry(String country) {
Country = country;
}
}
IndexTest.java
package com.amaker.action;
import java.util.List;
import org.apache.struts2.StrutsTestCase;
import com.opensymphony.xwork2.ActionProxy;
public class IndexTest extends StrutsTestCase{
public void testIndex() {
ActionProxy proxy = getActionProxy("/getinfo");
Index action = (Index)proxy.getAction();
request.setParameter("Author","Hemingway");
ActionProxy proxy1 = getActionProxy("/query");
try {
proxy1.execute();
} catch (Exception e1) {
e1.printStackTrace();
}
action.setIndex("0");
try {
proxy.execute();
List results = (List)request.getAttribute("list");
Book bk = (Book)results.get(0);
assertEquals(bk.getAge(),"1899.7.21--1961.7.2");
assertEquals(bk.getAuthorID(),7);
assertEquals(bk.getCountry(),"America");
assertEquals(bk.getISBN(),"9780099908500");
assertEquals(bk.getName(),"Hemingway");
assertEquals(bk.getPrice(),"54.30 yuan");
assertEquals(bk.getPublisher(),"Arrow");
assertEquals(bk.getPublisherDate(),"1994.8.18");
assertEquals(bk.getTitle(),"The Sun Also Rises");
} catch (Exception e) {
}
}
}
六:小結
我這裡用到的例子全是自己的代碼,希望能幫到大家。