單元測試 - spring + struts2

google 一下 struts2、unit test,大概會出現「Struts 2 JUnit Plugin」,用它來做單元測試當然沒問題,但是,現在的人寫 JavaEE 誰不用 spring ? 既然已經是 spring + struts2,就不用那麼麻煩了! 這裡舉個簡單的例子,這是一個查詢特定選區各候選人得票統計的小程式,執行出來的畫面如下:

source code 已經放在 https://github.com/twleader/DemoSite/tree/master/MVCSite,有興趣的可以下載來看看。

針對程式裡的 AreaResultAction,我們應該如何進行單元測試? 說明如下:

  • AreaResultAction.java

說明前,當然先看一下程式碼…

  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 }

程式中的 findAreaName 是底下單元測試要測試的項目,至於 @Controller,其實並不是必要的,但是,加上去會有好處,加上之後,然後在 spring 設定檔中,透過 component-scan 讓它可以被 spring 自動載入。

<context:component-scan base-package="idv.steven.demo.dto,idv.steven.demo.action" />

上方的綠色部份,即是 struts action 所在的 package,全部的 action class 前都加上 @Controller 即可。

  • 單元測試
 1 package idv.steven.demo.action;
 2
 3 import static org.junit.Assert.*;
 4
 5 import java.util.Map;
 6
 7 import org.junit.After;
 8 import org.junit.Before;
 9 import org.junit.Test;
10 import org.junit.runner.RunWith;
11 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.test.context.ContextConfiguration;
13 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
14
15 import com.opensymphony.xwork2.ActionSupport;
16
17 @ContextConfiguration(locations={"classpath:beans-config.xml"})
18 @RunWith(SpringJUnit4ClassRunner.class)
19 public class AreaResultActionTest {
20     @Autowired
21     private AreaResultAction action;
22
23     @Before
24     public void setUp() throws Exception {
25
26     }
27
28     @After
29     public void tearDown() throws Exception {
30     }
31
32     @Test
33     public void testFindAreaName() throws Exception {
34         action.setElectionID("201201");
35         action.setCityName("高雄市");
36         String result = action.findAreaName();
37         assertEquals(ActionSupport.INPUT, result);
38
39         Map<String, String> map = action.getAreaNameList();
40         assertEquals(9, map.size());
41     }
42 }

上面是單元測試程式,測試 findAreaName 是否可以傳回預期的值,從程式碼可以看到,完全看不出是 web 程式,反正就用一般的 java class 的思考模式進行測試,line 34、35 將需要的參數傳入,然後執行要測試的 method (line 36),之後檢查傳回的結果是否正確! (line 37、40) 至於紅色部份就是前面強調的,在 action class 前加上 @Controller,在這裡就可以很方便的讓 spring 幫我們初始化並載入這個 class。

时间: 2024-10-25 06:43:37

單元測試 - spring + struts2的相关文章

【转】Visual Studio單元測試小應用-測執行時間

[转]Visual Studio單元測試小應用-測執行時間 Visual Studio的單元測試會記錄每一個測試的執行時間,如果有幾個Method要測效能,以前我會用Stopwatch,最近我都改用單元測試來測,快又簡單. Visual Studio的單元測試會記錄每一個測試的執行時間,如果有幾個Method要測效能,以前我會用Stopwatch,最近我都改用單元測試來測,快又簡單. 範例程式:有人說Catch不加Expection,因為不用匹配會比較快,我不相信,就來測測看. { for (i

[转] [Visual Studio 2012] 找回 建立單元測試 選單

原文链接:http://www.dotblogs.com.tw/yc421206/archive/2013/03/08/95920.aspx Step1.建立選單 在VS2012選單,Tools→Customize→Commands    找到Create Unit Tests後,先按Move Up,再按Move Down Step2.設定快捷鍵 1.搜索unit關鍵字,若是中文版則輸入"單元測試" 2.選擇EditorContextMenus.CodeWindow.CreateUni

unit test on spring + struts2

當 web 程式是用 spring + struts2 開發時,要怎麼對 action 做 unit test? 這裡提出說明,假設有個網頁如下面畫面所示: 這是查詢各選區某次選舉各候選人的得票數,當使用者選擇了「選舉場次」後,「縣市」的下拉選單要出現該次選舉所涉及的所有縣市,以供使用者選擇,這個程式的 action 如下所示: action 1 package idv.steven.demo.action; 2 3 import java.util.ArrayList; 4 import ja

[RL學習篇][#2] 簡單的grid_mdp測試程式

下方是用來簡單的測試 grid_mdp.py的程式,執行後會用隨機動作去跑動作. 1 import gym 2 import tensorflow 3 import random 4 from gym import wrappers 5 6 env = gym.make('GridWorld-v0') 7 8 env = wrappers.Monitor(env, './outputs/grid_mdp-experiment-', force=True) 9 10 for episode in

一次測試即學習的案例

一般工程人員都知道 TDD 的使用方式,也明白 UnitTest 對於程式碼品質有著良好的保護 但比較少去探討的另一個好處應該是「學習」這件事了 雖然一般來說我們寫 Testing 其實是針對已知的事物(Business logic)去做測試與保護 比較少做未知的探索測試,但在一般有寫 Testing 情況下,還是有機會學習的 (所以還是鼓勵大家多多寫測試 ) 以下我分享一個測試即學習的案例給各位小夥伴 這個案例其實很簡單,我寫了一個 UnitTest 想要測試 EPPlus 在讀取完我建立的

Postman - 測試 API 的好工具

POSTMAN in Google APP Store 因為工作的關係,常常寫一些 API 供 APP 使用.以前傻傻的,每次測試的時候都會自己刻一個 HTML 的表單,一個一個填入 input ,接著送出. 後來覺得這樣太慢了,就用 JavaScript 寫了一個程式來送, 可是效率都沒有很好,尤其是需要反覆測試更改條件的時候. 之後在同事的推薦下用了 Burpsuite ,而這套軟體確實是可以做到沒錯,但是讓人有一種「殺雞焉用牛刀」的感覺. 因此又陸續找了幾個模擬 HTTP requests

[DE0-NANO] HC-05藍芽模組實現與測試(二)

篇是接續  [DE0-NANO] HC-05藍芽模組實現與測試(一) 本篇主要功能是將RFS板與電腦連接.硬體程式與上一篇相同. 在NIOS軟體部分,我新增了一個SLAVE模式,把RFS板上的HC05設為被動模式(SLAVE). 操作步驟 -------------------------------------------------------------------------- 1. 下載 DE0_Nano.sof 2.斷掉RFS板子電源,按下BT_KEY後在接上RFS板子電源. (此時

Spring+Struts2+Mybatis框架搭建时的常见典型问题

搭建SSM框架时,总是遇到这样那样的问题,有的一眼就能看出来,有的需要经验的积累.现将自己搭建SSM框架时遇到的典型问题总结如下: 一.Struts2框架下的action中无法使用@Autowired自动注入Bean(运行时bean总是为null) 常见原因: A.Spring的配置文件中组件扫描路径错误(即<context:component-scan base-package="xx.xx" />配置错误). B.@Autowired声明的beanName错误,bean

spring+struts2+ibatis整合

与spring+springmvc+ibatis相比,只需作相应的修改即可完成框架的整合.具体配置如下: web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" x