這是查詢各選區某次選舉各候選人的得票數,當使用者選擇了「選舉場次」後,「縣市」的下拉選單要出現該次選舉所涉及的所有縣市,以供使用者選擇,這個程式的 action 如下所示:
- action
1 package idv.steven.demo.action; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.Map; 6 import java.util.TreeMap; 7 8 import idv.steven.demo.dao.CandidateDAO; 9 import idv.steven.demo.dao.ElectionDAO; 10 import idv.steven.demo.dto.Candidate; 11 import idv.steven.demo.dto.Election; 12 13 import org.apache.struts2.convention.annotation.Action; 14 import org.apache.struts2.convention.annotation.Result; 15 import org.slf4j.Logger; 16 import org.slf4j.LoggerFactory; 17 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.stereotype.Controller; 19 20 import com.opensymphony.xwork2.ActionSupport; 21 22 @Controller 23 public class AreaResultAction extends ActionSupport { 24 private static final long serialVersionUID = -213699129575326012L; 25 final static Logger logger = LoggerFactory.getLogger(AreaResultAction.class); 26 27 @Autowired 28 private ElectionDAO electionDAO; 29 30 @Autowired 31 private CandidateDAO candidateDAO; 32 33 private Map<String, String> electionList = new TreeMap<String, String>(); 34 private Map<String, String> cityNameList = new TreeMap<String, String>(); 35 private Map<String, String> areaNameList = new TreeMap<String, String>(); 36 private List<Candidate> candidateList = new ArrayList<Candidate>(); 37 38 private String electionID; 39 private String cityName; 40 private String areaName; 41 42 /** 43 * 將網頁導向「AreaResult.jsp」(「選區投票結果查詢」網頁) 44 */ 45 @Action(value = "/areaResult", results = { @Result(location = "/jsp/AreaResult.jsp", name = "success") }) 46 public String execute() throws Exception { 47 return SUCCESS; 48 } 49 50 /** 51 * 將查詢結果顯示在 Grid 52 * @return 53 */ 54 @Action(value = "/showAreaResult", results = { @Result(location = "/jsp/AreaResultGrid.jsp", name = "success") }) 55 public String showAreaResult() { 56 return SUCCESS; 57 } 58 59 /** 60 * 傳回選舉場次 61 * @return 62 */ 63 @Action(value = "/findElection", results = { @Result(name = "input", type = "json") }) 64 public String findElection() { 65 List<Election> list = electionDAO.findAll(); 66 for(Election item:list) { 67 electionList.put(item.getId(), item.getName()); 68 } 69 70 return INPUT; 71 } 72 73 /** 74 * 傳回縣市 75 * @return 76 */ 77 @Action(value = "/findCityName", results = { @Result(name = "input", type = "json") }) 78 public String findCityName() { 79 List<String> list = candidateDAO.findCityName(electionID); 80 for(String item:list) { 81 cityNameList.put(item, item); 82 } 83 84 return INPUT; 85 } 86 87 /** 88 * 傳回選區 89 * @return 90 */ 91 @Action(value = "/findAreaName", results = { @Result(name = "input", type = "json") }) 92 public String findAreaName() { 93 List<String> list = candidateDAO.findAreaName(electionID, cityName); 94 for(String item:list) { 95 areaNameList.put(item, item); 96 } 97 98 return INPUT; 99 } 100 101 @Action(value = "/findCandidate", results = { @Result(name = "input", type = "json") }) 102 public String findCandidate() { 103 candidateList = candidateDAO.findCandidate(electionID, cityName, areaName); 104 105 return INPUT; 106 } 107 108 //由網頁中取值 109 public Map<String, String> getElectionList() { 110 return electionList; 111 } 112 113 public Map<String, String> getCityNameList() { 114 return cityNameList; 115 } 116 117 public Map<String, String> getAreaNameList() { 118 return areaNameList; 119 } 120 121 public List<Candidate> getCandidateList() { 122 return candidateList; 123 } 124 125 //網頁 submit 時傳值過來 126 public void setElectionID(String electionID) { 127 this.electionID = electionID; 128 } 129 130 public void setCityName(String cityName) { 131 this.cityName = cityName; 132 } 133 134 public void setAreaName(String areaName) { 135 this.areaName = areaName; 136 } 137 138 }
使用者選擇「選舉場次」時,傳到 action 的是 electionID,「縣市」的下拉選單呼叫 findCityName 從資料庫取得所有縣市,以 json 格式傳給 jsp,jsp 再透過 getCityNameList 取得縣市資料,顯示於下拉選單中。了解整個使用者與系統間互動的流程非常重要,因為接下來要進行單元測試時,單元測試程式是要模擬成瀏覽器與這個系統互動。
- import jar file
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>${struts.version}</version> </dependency>
在開始單元測試前,先在 pom.xml 中配置如上的 jar file。
- 單元測試
1 package idv.steven.demo.action; 2 3 import static org.junit.Assert.*; 4 5 import java.io.UnsupportedEncodingException; 6 import java.util.HashMap; 7 import java.util.Map; 8 9 import javax.servlet.ServletException; 10 11 import org.apache.struts2.StrutsSpringTestCase; 12 import org.junit.After; 13 import org.junit.Before; 14 import org.junit.Test; 15 import org.junit.runner.RunWith; 16 import org.springframework.test.context.TestExecutionListeners; 17 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 18 import org.springframework.test.util.ReflectionTestUtils; 19 20 import com.opensymphony.xwork2.ActionContext; 21 22 @RunWith(SpringJUnit4ClassRunner.class) 23 @TestExecutionListeners({}) 24 public class AreaResultActionTest extends StrutsSpringTestCase { 25 @Override 26 protected String[] getContextLocations() { 27 return new String[] {"classpath:beans-config.xml"}; 28 } 29 30 @Before 31 public void setUp() throws Exception { 32 //這幾行一定要寫 33 //等價於在 web.xml 中設定 <init-param> 參數 34 Map<String, String> dispatcherInitParams = new HashMap<String, String>(); 35 ReflectionTestUtils.setField(this, "dispatcherInitParams", dispatcherInitParams); 36 //載入 struts 設定檔 37 dispatcherInitParams.put("config", "struts-default.xml,struts-plugin.xml,struts.xml"); 38 39 super.setUp(); 40 } 41 42 @After 43 public void tearDown() throws Exception { 44 super.tearDown(); 45 } 46 47 @Test 48 public void testFindCityName() throws UnsupportedEncodingException, ServletException { 49 //初始化 http 相關環境變數 request、response ... 50 initServletMockObjects(); 51 52 //jsp要submit那些欄位的資料到action? 透過 request.setParameter傳入。 53 request.setParameter("electionID", "201201"); 54 executeAction("/findCityName"); 55 56 //執行完action,取得action物件。 57 AreaResultAction action = (AreaResultAction) ActionContext.getContext().getActionInvocation().getAction(); 58 //jsp網頁中,縣市的下拉選單呼叫 cityNameList 取得縣市資料。 59 Map<String, String> cities = action.getCityNameList(); 60 for(String city:cities.keySet()) { 61 System.out.println(city); 62 } 63 } 64 }
- 上面單元測試程式 22~28 行要特別注意,每個單元測試程式都要繼承 StrutsSpringTestCase 這個類別,透過這個類別單元測試程式才能模擬出 web 的環境,26~28 行 override getContextLocations 這個 method,因為 StrutsSpringTestCase 會呼叫這個 method 以取得 spring 設定檔,我的設定檔名為 beans-config.xml。
- setUp method 必須進行一些每個 method 測試前要進行的工作,這裡如上面的注解所說明的,載入 web.xml 及 struts 設定檔。
- 如果我們進行的單元測試要用到 http 相關的環境變數,一定要呼叫 initServletMockObjects (50行),這樣就可以使用 request、response 等變數了。
- 53~54行,透過 request 將 electionID 傳給 action,這相當於 jsp 透過 request 將 electionID 傳給 action。
- 57行,執行完 action 立即取得該 action 的物件,之後即可進行驗證。
沒有留言:
張貼留言