版权声明:大家好,我是笨笨,笨笨的笨,笨笨的笨,转载请注明出处,谢谢! https://blog.csdn.net/jx520/article/details/89646441
Struts2 单元测试
第一添加依赖
<!-- JUnit 输出日志用 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- JUnit 输出日志用 -->
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.16.0</version>
<scope>test</scope>
</dependency>
<!-- Struts action 单元测试用 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>${struts.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
指定 spring 配置文件位置
这个不算坑。如果你的配置文件不在默认的位置,设置一下就好了。
/jerry-demo/src/main/resources/config/applicationContext.xml
@Override
protected String[] getContextLocations() {
//重设 Spring XML路径
return new String[] { "classpath*:config/applicationContext.xml" };
}
坑一【request,response 为 null】
因为我给所有 Action
加了个父类 BaseAction
,并在里面定义了 request, response
方便子类。
public class BaseAction extends ActionSupport {
protected HttpServletRequest request = ServletActionContext.getRequest();
protected HttpServletResponse response = ServletActionContext.getResponse();
...
}
但是 org.apache.struts2.StrutsTestCase#getActionProxy(String uri)}
先创建 ActionProxy
后注入 request, response
导致我所有的 Action
中 request, response
都变成 null
了。所以我要在它访问前手动注入一下。
@Override
protected void setUp() throws Exception {
super.setUp();
ServletActionContext.setServletContext(servletContext);
ServletActionContext.setRequest(request);
ServletActionContext.setResponse(response);
}
当然除了上面这点,还有些常用的功能也要加上,所以最后面我们会整理一下。
坑二【struts.xml
必须放在 classpath
下】
它默认到 /jerry-demo/src/main/resources/struts.xml
下找 struts 配置文件。你不放这里它就给你 404
Dispatcher#sendError: 404
如果你的配置文件在/jerry-demo/src/main/resources/strutsConfig/struts.xml
不方便移过来,那就创建一个/jerry-demo/src/main/resources/struts.xml
引用它吧。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<include file="strutsConfig/struts.xml"></include>
</struts>
完整的代码例子
日志工具类
package com.jerry.tools;
import org.junit.Rule;
import org.junit.contrib.java.lang.system.SystemErrRule;
import org.junit.contrib.java.lang.system.SystemOutRule;
/**
* JUnit 日志输出工具类
*/
public class JUnitLogTool {
// 正确输出
@Rule
protected final static SystemOutRule logOut = new SystemOutRule();
// 错误输出
@Rule
protected final static SystemErrRule logErr = new SystemErrRule();
/**
* 用于测试中,向控制台输出信息
* @author jerryjin
*/
public static class Log {
public void out(String msg) {
System.out.println("----------------------log.out begin-------------------------------");
System.out.println(msg);
System.out.println("-----------------------log.out end--------------------------------");
logOut.getLog();
}
public void err(String msg) {
System.out.println("----------------------log.err begin-------------------------------");
System.err.println(msg);
System.out.println("-----------------------log.err end--------------------------------");
logErr.getLog();
}
}
public String getMsg(String msg, Object... args) {
return String.format(msg, args);
}
}
断言工具类
根据具体情况,添加几个方法。
package com.jerry.tools;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import java.util.Map;
import com.jerry.dto.IBaseDTO;
/**
* Assert 工具类
*/
public class AssertTool {
/**
* 期望 resultMap 中 msg 的值为 success
* @param resultMap 待验证的结果map
*/
public static void assertMapMsg(Map<String, Object> resultMap) {
assertMapMsg(resultMap, "success");
}
/**
* 期望 resultMap 中 msg 的值为 expectedMsg
* @param resultMap 待验证的结果map
* @param expectedMsg 待验证的结果值。通常是 "success"
*/
public static void assertMapMsg(Map<String, Object> resultMap, String expectedMsg) {
assertEquals(expectedMsg, (String) resultMap.get("msg"));
}
/**
* 期望触发一个异常
* @param dto
* @param message
*/
public static void assertException(IBaseDTO<?, ?> dto, String message ){
try {
dto.validate();
} catch (Exception e) {
assertTrue(e instanceof IllegalArgumentException);
assertEquals(message, e.getMessage());
return ;
}
assertTrue("期望的异常: " + message + "。未触发", false);
}
}
测试基类【带日志输出】
package com.jerry;
import com.jerry.tools.JUnitLogTool;
import junit.framework.TestCase;
/**
* {@linkplain JUnit} 单元测试基类
* <br>支持 JUnit 中日志输出
*/
public class BaseLogTest extends TestCase {
// JUnit日志输出工具类
protected static com.jerry.tools.JUnitLogTool.Log log = new JUnitLogTool.Log();
}
测试基类【带日志输出 + Spring支持】
package com.jerry;
import java.util.Map;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jerry.dto.IBaseDTO;
import com.jerry.tools.JUnitLogTool;
import junit.framework.TestCase;
/**
* {@linkplain JUnit} + {@linkplain Spring} 单元测试基类
* <br>支持 JUnit 中日志输出
*/
public class BaseTest extends TestCase {
// 初始化上下文;
protected static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "config/applicationContext.xml");
// JUnit日志输出工具类
protected static com.jerry.tools.JUnitLogTool.Log log = new JUnitLogTool.Log();
public <T> T getBean(Class<T> requiredType) {
return context.getBean(requiredType);
}
public Object getBean(String requiredType) {
return context.getBean(requiredType);
}
protected void assertResultMap(Map<String, Object> resultMap) {
assertEquals("success", (String) resultMap.get("msg"));
log.out(resultMap.toString());
}
public void assertException(IBaseDTO<?, ?> dto, String message ){
try {
dto.validate();
} catch (Exception e) {
assertTrue(e instanceof IllegalArgumentException);
assertEquals(message, e.getMessage());
return ;
}
assertTrue("期望的异常: " + message + "。未触发", false);
}
}
测试基类【带日志输出 + Spring支持 + Struts2支持】
package com.jerry;
import javax.swing.Spring;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsSpringTestCase;
import com.jerry.tools.JUnitLogTool;
/**
* {@linkplain Struts2} + {@linkplain JUnit} + {@linkplain Spring} 单元测试基类
* <br>支持 JUnit 中日志输出
*/
public class BaseStruts2Test extends StrutsSpringTestCase {
// ----------------------------------- struts junit spring 开始 --------------------------------------------
@Override
protected String[] getContextLocations() {
//重设 Spring XML路径
return new String[] { "classpath*:config/applicationContext.xml" };
}
/**
* 从 Spring 容器获取 bean
* @param clazz 目标类型
* @return
*/
public <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
/**
* 从 Spring 容器获取 bean
* @param className 目标类名
* @return
*/
public Object getBean(String className) {
return applicationContext.getBean(className);
}
/**
* 因为我给所有 Action 加了个父类 BaseAction,并在里面定义了 request, response 但是
* {@link org.apache.struts2.StrutsTestCase#getActionProxy(String uri)} 先创建 ActionProxy 后注入 request, response
* 导致我所有的 Action 中 request, response 都变成 null 了。所以要在这里手动注入一下
*/
@Override
protected void setUp() throws Exception {
super.setUp();
ServletActionContext.setServletContext(servletContext);
ServletActionContext.setRequest(request);
ServletActionContext.setResponse(response);
}
// ----------------------------------- struts junit spring 结束 --------------------------------------------
// ----------------------------------- log 开始 --------------------------------------------
// JUnit日志输出工具
protected static com.jerry.tools.JUnitLogTool.Log log = new JUnitLogTool.Log();
// ----------------------------------- log 结束 --------------------------------------------
}
测试用例
如果上面已经执行这,这里再执行, resultJson 里就会两次执行的结果
在同一个用例中,如果多次发请求,executeAction 取返的结果也是多次的叠加。
public class MoveTicketJsonTest extends BaseStruts2Test {
private IMoveTicketService moveTicketService = null;
protected void setUp() throws Exception {
super.setUp();
// 这里用到 Service 主要是取点数据方便测试。作为请求的参数。
moveTicketService = getBean(IMoveTicketService.class);
}
public void testGetTicke() throws Exception {
// -------------------------- 准备请示参数 ----------------------------
String id = "666";
String sign = JerryCrypt.sign(id+teleportation);// 签名
// ---------------------------- 模拟请求 ----------------------------
//设置 请求参数
request.setParameter("id", id);
request.setParameter("sign", sign);
//获取要测试Action
ActionProxy proxy = getActionProxy("/json/get_Ticke.action");
MoveTickeJson action = (MoveTickeJson ) proxy.getAction();
//执行 Action 并获取 return 结果 (success)
String result = proxy.execute();
assertEquals("success", result);
// ------------------------- 验证请求结果验证 --------------------------
// dataMap 是自己在控制器中定义的保存结果的map
Map<String, Object> dataMap = action.getDataMap();
AssertTool.assertMapMsg(dataMap);
log.out(dataMap.toString());
}
public void testGetDetailTicke() throws Exception {
//设置 请求参数
request.setParameter("id", "65");
// 执行 executeAction 得到的是接口返回的 JSON 数据
String resultJson = executeAction("/json/detail_Ticke.action");
JSONObject json = JSONObject.parseObject(resultJson);
assertEquals("success", json.getString("status"));
log.out(resultJson);
}
}