junit不能測(cè)struts的action,httpunit也只能測(cè)servlet。用struts作項(xiàng)目的時(shí)候無(wú)法方便的對(duì)action層做單元測(cè)試一直是我的心頭大恨。現(xiàn)在好了,我們有了StrutsTestCase。按照網(wǎng)上的介紹,StrutsTestCase用起來(lái)應(yīng)該是非常簡(jiǎn)單的,只要下了jar包回來(lái)引用到工程里面就可以了。實(shí)際上可能也差不多--如果你運(yùn)氣不象我這么臭的話。
在sourceforge上隨便挑其中一個(gè)鏡象的下載地址:
http://aleron.dl.sourceforge.net/sourceforge/strutstestcase/strutstest213-1.2_2.4.zip
flashget回來(lái),放到j(luò)builder的userhome里面,找一個(gè)struts action創(chuàng)建test case,創(chuàng)建的時(shí)候吧test case的基類(lèi)改為 MockStrutsTestCase,測(cè)試的方法一個(gè)都不用選(因?yàn)槲覀兪且槍?duì)action的具體每一個(gè)邏輯分支測(cè)試而不是具體的某一個(gè)方法)。創(chuàng)建成功后添加一個(gè)測(cè)試:
public void testSuccessfulRefresh()
{
setRequestPathInfo("/RefreshSystemData");
actionPerform();
verifyForward("success");
}
嘿嘿,我精心挑了一個(gè)沒(méi)有參數(shù)的action來(lái)實(shí)驗(yàn)。
一切看起來(lái)很順利。run test,噩夢(mèng)開(kāi)始了:
java.lang.NullPointerException
at servletunit.struts.MockStrutsTestCase.getActionServlet(MockStrutsTestCase.java:331)
at servletunit.struts.MockStrutsTestCase.tearDown(MockStrutsTestCase.java:130)
at hospital.tongren.oa.system.action.TestRefreshSystemDataAction.tearDown(TestRefreshSystemDataAction.java:34)
...(Click for full stack trace)...
還好我沒(méi)有開(kāi)音箱,不然又是一大炮轟出來(lái)。
看來(lái)要調(diào)試了,先去同一個(gè)地方下了StrutsTestCase原碼回來(lái)
http://aleron.dl.sourceforge.net/sourceforge/strutstestcase/strutstest-213-src.zip
加進(jìn)userhome里面的source。debug進(jìn)去,跟到org.apache.struts.action.ActionServlet里面,出錯(cuò)的地方是:
InputStream input =
getServletContext().getResourceAsStream("/WEB-INF/web.xml");
try {
digester.parse(input);
} catch (IOException e) {
....
input 為空指針。不知道為什么ServletContextSimulator在模擬ServletContext的時(shí)候沒(méi)能夠正確的找到webmodule的位置。上網(wǎng)搜了好一會(huì)兒文檔,在 http://strutstestcase.sourceforge.net/api/servletunit/struts/MockStrutsTestCase.html 中發(fā)現(xiàn)了這樣一段:
NOTE: By default, the Struts ActionServlet will look for the file WEB-INF/struts-config.xml, so you must place the directory that contains WEB-INF in your CLASSPATH. ...
先照它說(shuō)的試試把webmodule路徑放進(jìn)classpath中,沒(méi)有用。
往下看,發(fā)現(xiàn)了這個(gè)好東東:setContextDirectory。在startup中加一句:
this.setContextDirectory(new File("E:\\projectPath\\webModulePath\\"));
終于把那個(gè)空指針給過(guò)了。但是報(bào)一個(gè)新的異常:
junit.framework.AssertionFailedError: received error 400 : Invalid path /RefreshSystemData was requested
at servletunit.HttpServletResponseSimulator.sendError(HttpServletResponseSimulator.java:463)
at org.apache.struts.action.RequestProcessor.processMapping(RequestProcessor.java:684)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:242)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at servletunit.struts.MockStrutsTestCase.actionPerform(MockStrutsTestCase.java:394)
at hospital.tongren.oa.system.action.TestRefreshSystemDataAction.testSuccessfulRefresh(TestRefreshSystemDataAction.java:51)
...(Click for full stack trace)...
找不到strutsconfig里面配置的path。strutsconfig是在web.xml里面配置的,應(yīng)該還是web.xml沒(méi)找到造成的,那么就指定strutsconfig文件的位置咯:
setConfigFile("E:\\......\\struts-config.xml");
終于可以運(yùn)行起來(lái)了。
隨后發(fā)現(xiàn),如果 setServletConfigFile("E:\\....\\WEB-INF\\web.xml");的話MockStrutsTestCase也能夠根據(jù)web.xml中的配置找到strutsconfig文件。
最后把上面用到的絕對(duì)地址E:\\...全部改為相對(duì)地址:
setContextDirectory(new File("modulePath\\"));
setServletConfigFile("modulePath\\WEB-INF\\web.xml");
// this.setConfigFile("modulePath\\WEB-INF\\config\\system\\struts-config.xml");
血吐完了,繼續(xù)郁悶,為什么別人都不用配置的這么麻煩呢?到底我做錯(cuò)了什么,還是jbuilder的錯(cuò)?
CactusStrutsTestCase也沒(méi)配起,好像要加個(gè)什么包吧,再看看先。
[
點(diǎn)擊此處收藏本文]