openSymphony 2.1.2 と struts 2.3.8 を使用するプロジェクトに取り組んでいます。
ただし、そのコード ベースでは、古いバージョンの openSymphony と struts 用に作成されたピース コードを適用しようとしています。
そのコードは次のとおりです。
http://www.lischke-online.de/index.php/java/action-unit-testing-with-struts-2-0-part-2
(補足として、別のフレームワークに基づくシステムで、継承したプロジェクトからの struts アクションの実行をシミュレートできるようにするために、そのコードが必要です。)
次の段落に問題があります。
final StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory("auto", "true", servletContext);
ObjectFactory.setObjectFactory(ssf);
2 行目で、次のエラーが表示されます。The method setObjectFactory(StrutsSpringObjectFactory) is undefined for the type ObjectFactory
ただし、ObjectFactory の javadoc を見ると、アクションの実行時に使用される特定のObjectFactory
(例: StrutsSpringObjectFactory
) を設定できる代替メソッドが見つかりません。では、新しい API でそのObjectFactory
ような特定をどのように設定すればよいでしょうか?ObjectFactory
更新されたコード:
static {
sessionMap = new HashMap<String, Object>();
// Create fake back end here.
// ...
// ===== Struts setup:
// Create and use a file system resource loader otherwise Tiles will not find
// our configuration file. The default resource loader is able to find struts.xml
// if it is in the classpath, but not tiles.xml.
final FileSystemResourceLoader loader = new FileSystemResourceLoader();
final String[] config = new String[] { "WEB-INF/classes/struts.xml" };
servletContext = new MockServletContext(loader);
final XmlWebApplicationContext appContext = new XmlWebApplicationContext();
// Link the servlet context and the Spring context.
appContext.setServletContext(servletContext);
appContext.setConfigLocations(config);
appContext.refresh();
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
appContext);
servletContext.addInitParameter(BasicTilesContainer.DEFINITIONS_CONFIG, "WEB-INF/tiles.xml");
// Creating the tiles listener statically (not via class loader).
final StrutsTilesListener tilesListener = new StrutsTilesListener();
final ServletContextEvent event = new ServletContextEvent(servletContext);
tilesListener.contextInitialized(event);
// Use spring as the object factory for Struts
//this code not working anymore with struts 2.3.2:
//final StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory("auto", "true", servletContext);
//ObjectFactory.setObjectFactory(ssf);
//my change: (original note working with newer version of struts)
//StrutsSpringObjectFactory.setObjectFactory(ssf);
//(*) original location.
// Dispatcher is the guy that actually handles all requests. Pass in
// an empty. Map as the parameters but if you want to change stuff like
// what config files to read, you need to specify them here
// (see Dispatcher's source code)
dispatcher = new Dispatcher(servletContext, new HashMap<String, String>());
dispatcher.init();
Dispatcher.setInstance(dispatcher);
//(*) moved to here:
//http://stackoverflow.com/questions/15821643/setting-strutsspringobjectfactory-as-my-current-objectfactory?noredirect=1#comment22519072_15821643
final StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory("auto", "true", "false", servletContext, "false", dispatcher.getContainer());
}
Webアプリケーション内からテストを呼び出すときに、そのコードで得たスタックトレース(デプロイされた戦争):
08:50:28,471 WARNING [javax.enterprise.resource.webcontainer.jsf.lifecycle] (http--127.0.0.1-8080-1) #{accountLookupBean.lookupAccounts()}: java.lang.ExceptionInInitial
izerError: javax.faces.FacesException: #{accountLookupBean.lookupAccounts()}: java.lang.ExceptionInInitializerError
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at javax.faces.component.UICommand.broadcast(UICommand.java:315) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
at javax.faces.component.UIData.broadcast(UIData.java:1093) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
at javax.faces.component.UIData.broadcast(UIData.java:1093) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
at javax.faces.component.UIData.broadcast(UIData.java:1093) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.10.Final.jar:]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:154) [jboss-as-web-7.1.0.Final.jar:7.1.0.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.10.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.10.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.10.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.10.Final.jar:]
at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_29]
Caused by: javax.faces.el.EvaluationException: java.lang.ExceptionInInitializerError
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.
0.Final]
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
... 23 more
Caused by: java.lang.ExceptionInInitializerError
at com.myapp.services.AccountLookupServiceImpl.getRows(AccountLookupServiceImpl.java:38) [classes:]
at com.myapp.beans.AccountLookupBean.lookupAccounts(AccountLookupBean.java:39) [classes:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_29]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_29]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_29]
at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_29]
at org.apache.el.parser.AstValue.invoke(AstValue.java:262) [jbossweb-7.0.10.Final.jar:]
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278) [jbossweb-7.0.10.Final.jar:]
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0
.Final]
... 24 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/classes/struts.xml];
nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/classes/struts.xml]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341) [spring-beans-3.2.1.RELEASE.jar:3.2.1.REL
EASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302) [spring-beans-3.2.1.RELEASE.jar:3.2.1.REL
EASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174) [spring-beans-3.2.1.RELEASE
.jar:3.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209) [spring-beans-3.2.1.RELEASE
.jar:3.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180) [spring-beans-3.2.1.RELEASE
.jar:3.2.1.RELEASE]
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125) [spring-web-3.2.1.RELEASE.jar:3.2.1.R
ELEASE]
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94) [spring-web-3.2.1.RELEASE.jar:3.2.1.RE
LEASE]
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130) [spring-context-
3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537) [spring-context-3.2.1.RELEASE.jar:
3.2.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451) [spring-context-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at com.myapp.softgems.ActionBaseTestCase.<clinit>(ActionBaseTestCase.java:70) [classes:]
... 34 more
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/classes/struts.xml]
at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:140) [spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:328) [spring-beans-3.2.1.RELEASE.jar:3.2.1.REL
EASE]
... 44 more
更新 2:
アクションをテストできるようにしたい理由は、単にプロジェクト エクスプローラーからアクションを右クリックして、「JUnit として実行」を右クリックできるようにするためではありません。実際には、Web アプリケーションの一部としてテストを実行したいと考えています。
つまり、サービス クラスの 1 つから次のコードを呼び出そうとしています。
DataTest test = new DataTest("testDataAction");
JUnitCore jUnitCore = new JUnitCore();
jUnitCore.run(test);
なぜなら、DataTest では、DataAction を execute() しようとするからです。そのアクションは、厄介なデータベースロジックを呼び出し、最終的にデータを返します。サービスのためにそのデータが必要です。Action が正確に何をするかを理解しようとする代わりに、単純に execute() してデータを取得したいと思います。私がやろうとしている方法は、アクションを実行するテストを実行することです。
私の struts.xml は、私が構築しているプロジェクトに直接含まれていません。これが私の状況です。私の新しいプロジェクトをプロジェクト A としましょう。そして、私が依存しているレガシー Struts プロジェクト、プロジェクト B. プロジェクト A は、他のフレームワーク (JSF & Spring) によって構築されています。プロジェクト B は、UI にストラットを使用します。しかし、そのアクションは非常に厄介な方法で記述されていたため、多くの DB アクセス ロジックがアクション内に直接記述されていました。したがって、プロジェクト B のロジックを使用し、それを書き直さない場合、一時的な解決策 (達成しようとしている) は、対応する要求データを使用してプロジェクト B のアクションを実行することです。その方法は、A のサービス クラス内で、B のアクションに対してテストを実行することです。
プロジェクト B は war ファイルとしてパックされているため、プロジェクト A の Maven でそれを再利用する私の方法は、プロジェクト A のオーバーレイとして定義することです。プロジェクト B のクラスパスからのクラスおよびその他のリソースは jar にパックされます。次に、プロジェクト AI でその jar に依存します。そのため、struts.xml は、プロジェクト B のクラスと xml を含む jar に存在します。コンパイル時には、プロジェクト A はプロジェクト A の jar 内の struts.xml しか見ることができません。
プロジェクト A をパックするときだけ、war B がアンパックされ、その内容 (struts.xml を含む) がプロジェクト A のターゲット フォルダーにコピーされ、A + B が 1 つの war としてパックされます。(最終戦争では、struts.xml は jar B と最終戦争内の WEB-INF/classes の両方にあります。
したがって、実際には、テストを右クリックして「junitとして実行」してテストを実行しようとすると、クラスパスの一部のWEB-INF /クラスでstruts.xmlが見つからないはずです-最初にそのようなものはありません私のワークスペース、作成された戦争でのみ。2 つ目は、(上で示したように) 戦争の中からのみテストを実行しようとすることです。当時、WEB-INF/classes/struts.xml があったのですが、なぜ見つからなかったのでしょうか?