Spring Test+Struts 2 Convention制御層ユニットテスト

8357 ワード

初めてブログを書いて、今日Spring Testを勉強したときに出会った問題を記録します.
 
一、問題の説明
開涛ブログを参照自分のプロジェクトにSpring Testを加入し、そのウェブサイトは以下の通りです.http://jinnianshilongnian.iteye.com/blog/1469524
次に、私の制御層テストコードを示します.
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({})
public class LoginActionTest extends StrutsSpringTestCase {
	
	/**
	 *     
	 * classpath*:applicationContext.xml
	 * @throws Exception
	 */
	@Override
	protected String[] getContextLocations() {
		return new String[]{"classpath:applicationContext.xml"};
	}
	
	@Before  
    public void setUp() throws Exception {  
        //1   Struts2      
        //        web.xml  <init-param>        
        Map<String, String> dispatcherInitParams = new HashMap<String, String>();  
        ReflectionTestUtils.setField(this, "dispatcherInitParams", dispatcherInitParams);  
        //1.1   Struts        
        dispatcherInitParams.put("config", "struts-default.xml,struts-plugin.xml,struts.xml");  
        super.setUp();  
    }  

	/**
	 * @throws Exception 
	 * 
	 */
	@Test
	public void testWelcome() throws Exception {
		String output = executeAction("/user/login!welcome.action");
        assertEquals(Action.SUCCESS, output);
	}
	
	@Test
	public void testDeal() throws Exception {
		request.setParameter("username", "  ");
		request.setParameter("password", "1");
		
		ActionProxy proxy = getActionProxy("/user/login!deal.action");
        assertNotNull(proxy);
        
        LoginAction action = (LoginAction) proxy.getAction();
        assertNotNull(action);
        String result = proxy.execute();
        assertNull(result);
        
//        String username = (String) findValueAfterExecute("username");
//        String password = (String) findValueAfterExecute("password");
//        assertEquals("  ", username);
//        assertEquals("1", password);
        System.out.println(response.getContentAsString());
        assertEquals("  ", action.getModel().getUsername());
        assertEquals("1", action.getModel().getPassword());
	}

}

 
以下はJUnit 4のエラー記録です.
  Spring Test + Struts2 Convention 控制层单元测试_第1张图片
 
これはコンソールから出力されたエラーです.
 
2016-01-21 15:18:09,848  WARN (org.springframework.mock.web.MockServletContext:319) - Couldn't get resource paths for class path resource [WEB-INF/jsp/user/]
java.io.FileNotFoundException: class path resource [WEB-INF/jsp/user/] cannot be resolved to URL because it does not exist
	at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:187)
	at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:48)
	at org.springframework.mock.web.MockServletContext.getResourcePaths(MockServletContext.java:303)
	at org.apache.struts2.convention.DefaultResultMapBuilder.createFromResources(DefaultResultMapBuilder.java:252)
	at org.apache.struts2.convention.DefaultResultMapBuilder.build(DefaultResultMapBuilder.java:189)
	at org.apache.struts2.convention.PackageBasedActionConfigBuilder.createActionConfig(PackageBasedActionConfigBuilder.java:933)
	at org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildConfiguration(PackageBasedActionConfigBuilder.java:702)
	at org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildActionConfigs(PackageBasedActionConfigBuilder.java:348)
	at org.apache.struts2.convention.ClasspathPackageProvider.loadPackages(ClasspathPackageProvider.java:53)
	at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:268)
	at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
	at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:445)
	at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:489)
	at org.apache.struts2.util.StrutsTestCaseHelper.initDispatcher(StrutsTestCaseHelper.java:54)
	at org.apache.struts2.StrutsTestCase.initDispatcher(StrutsTestCase.java:229)
	at org.apache.struts2.StrutsTestCase.setUp(StrutsTestCase.java:209)
	at web.user.LoginActionTest.setUp(LoginActionTest.java:47)

 
二、解決方法
参照http://blog.csdn.net/jammiwang19870815/article/details/9175607自分のResourceLoaderを追加すれば、解決できます.ResourceLoaderパスの問題に注意して、実際のパスと一致するように書きます.次は私のコードです.
public class MyResourceLoader extends DefaultResourceLoader {
	private static final Logger logger = LoggerFactory.getLogger(MyResourceLoader.class);

	@Override
	public Resource getResource(String location) {
		if(location != null && location.startsWith("/WEB-INF/")) {
			logger.info(location);
			URL path = null;
			try {
				String str = "file:/" + System.getProperty("user.dir") + "/WebRoot" + location;
				logger.info(str);
				path = new URL(str);
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
			return new UrlResource(path);
		}
		return super.getResource(location);
	}
	
}

コメントには、次のような別のソリューションが記載されています.
log4j.propertiesに追加:log 4 j.logger.org.springframework.mock.web.MockServletContext=error
この方法はコンソールの出力を遮断しただけで、テストはまだ合格していないので、だめです!
 
三、まとめ
1、なぜtestDeal()テスト方法が合格したのに、testWelcome()テスト方法が合格しなかったのですか.
これは、testDeal()に対応するLoginActiondeal()メソッドreturnがnull、testWelcome()に対応するLoginActionwelcome()メソッドreturnがsuccess、WEB-INF/jsp/user/loginに対応するためである.jspは、classpathの下のパスをデフォルトで検索するため、エラーが見つかりません.これがResourceLoaderを書き換える理由です.
説明:これが間違っているかどうかはあなたが書いたActionと関係がありますが、この例はこのように書いています.
2、getContextLocationsデフォルトはclasspath*:アプリケーションContext.xmlなので、この例のgetContextLocations()メソッドは複写しなくてもよい.
3、テストクラスに@RunWith(SpringJUnit 4 ClassRunner.class)@TestExecutionListeners({})注釈を追加しないと@Ignoreを使用してテストを無視できません.また、デフォルトではすべての方法でテストが行われます.すなわち、デフォルトでは@Test注釈が追加されていますが、前の2つの注釈を追加するとJUnit 4の注釈が正常に使用できます.なぜなのか分かりません.
 
ふろく
最後にLoginActionを補充します.
@SuppressWarnings("serial")
@Namespace("/user")
public class LoginAction extends StrutsAction<User> {
	
	@Autowired
	private UserService userService;
	
	public String welcome() {
		logger.info("    ");
		return SUCCESS;
	}
	
	/**
	 *   
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public String deal() throws UnsupportedEncodingException {
		Result result = null;
		boolean flag = userService.exist(model.getUsername());
		if(flag) {//  
			flag = userService.exist(model);
			if(flag) {
				//  user   session 
				Map<String, Object> session = ActionContext.getContext().getSession();
				session.put("username", model.getUsername());
				String resultUrl = Struts2Utils.getRequest().getContextPath() + "/main.action";
				result = new Result(Result.SUCCESS, "", resultUrl);
			} else {
				result = new Result(Result.ERROR, "    ", "");
			}
		} else {
			result = new Result(Result.ERROR, "     ", "");
		}
		Struts2Utils.renderText(result);
		return null;
	}
	
	/**
	 *   
	 * @return
	 */
	public String logout() {
		Map<String, Object> session = ActionContext.getContext().getSession();
		session.remove("username");
		return "logout";
	}

	
}