S2Unit4でHttpServletRequestをモックにしたテストが失敗する
EasyMockサポートを使ってテストをしたときのことです。
HttpServletRequestに@EasyMock(register=true)を付けてS2コンテナからHttpServletRequestを取得しようとすると、TooManyRegistrationRuntimeExceptionが発生しました。昔Junit3でやったときは確かにできたので、きっとどこかに変更があったのでしょう。
調べてみるとInternalTestContextImplがHttpServletExternalContextComponentDefRegisterをS2コンテナにセットしており、このRegisterがHttpServletRequestをS2コンテナに登録していました。EasyMockSupportもregister=trueのモックをコンテナに登録するので、コンテナからHttpServletRequestを取得するときにTooManyRegistrationRuntimeExceptionが発生してしまっていたのでした。
なんとかならないか?ということで、なんとかしてみました。
s2junit4.dicon
<!-- <component name="context" class="org.seasar.framework.unit.impl.InternalTestContextImpl"/> --> <component name="context" class="jp.co.ise_group.context.OreOreInternalTestContextImpl"/>
InternalTestContextImplではなく、オレオレInternalTestContextImplを使います。
OreOreInternalTestContextImpl.java
public class OreOreInternalTestContextImpl extends InternalTestContextImpl { @InitMethod @Override public void init() throws Throwable { super.init(); container.setExternalContextComponentDefRegister( new OreOreHttpServletExternalContextComponentDefRegister()); } }
HttpServletExternalContextComponentDefRegisterを使っている限りどうにもならないので、OreOreHttpServletExternalContextComponentDefRegisterを使うように差し替えます。
OreOreHttpServletExternalContextComponentDefRegister
public class OreOreHttpServletExternalContextComponentDefRegister implements ExternalContextComponentDefRegister { private S2ContainerImpl container; public void registerComponentDefs(S2Container container) { this.container = (S2ContainerImpl) container; registerIfNotExist(new HttpServletRequestComponentDef()); registerIfNotExist(new HttpServletResponseComponentDef()); registerIfNotExist(new HttpSessionComponentDef()); registerIfNotExist(new ServletContextComponentDef()); registerIfNotExist(new ApplicationMapComponentDef()); registerIfNotExist(new InitParameterMapComponentDef()); registerIfNotExist(new SessionMapComponentDef()); registerIfNotExist(new RequestMapComponentDef()); registerIfNotExist(new CookieMapComponentDef()); registerIfNotExist(new RequestHeaderMapComponentDef()); registerIfNotExist(new RequestHeaderValuesMapComponentDef()); registerIfNotExist(new RequestParameterMapComponentDef()); registerIfNotExist(new RequestParameterValuesMapComponentDef()); } private void registerIfNotExist(ComponentDef def) { Object key = def.getComponentClass(); if (key == null || !container.hasComponentDef(key)) { container.register0(def); } } }
EasyMockサポートのページに「モックの登録はS2コンテナの初期化前に行われる」と書いてあったので、何かすでに登録されていればコンポーネントを登録しないようにしてみました。インジェクションされる側のフィールド名をhttpServletRequestにしないとだめかな?とも思いましたが、requestでもちゃんとインジェクションされます。