S2Junitããã¹ã対象ã³ã³ãã¼ãã³ãã®ä¾åã³ã³ãã¼ãã³ããå¾ããè¨å®ããå ´åã«æ£ããDIãã¦ãããªãäºè±¡ã®è§£æ±ºç
æ´æ°å±¥æ´
- 2011-06-24 ä¾åã³ã³ãã¼ãã³ããåç §ãã¦ãã³ã³ãã¼ãã³ããä¸æ¸ãã§ããªãã£ãã®ãä¿®æ£
- 2012-02-24 å®è£ æ¹æ³ãå¤§å¹ ã«å¤æ´ãä»ã¾ã§ã®å®è£ ãè¬ã®ã¡ã¢ãªãªã¼ã¯ã¨ãããããã
ã¢ããã¼ã·ã§ã³
S2Junitã§mockitoã使ãããã£ãã®ã§ãããã³ã¼ãçã«ã¯ãããªã®ãæ³å®ãã¦ããã
@RunWith(Seasar2.class) public class HogeLogicTest { HogeLogic hogeLogic; // app.diconã§ã³ã³ãã¼ãã³ããç»é²ããã¦ã // HogeLogicã®å®è£ ãä¾åãã¦ããã³ã³ãã¼ãã³ããHogeLogicã®çææã«DIãããã // app.diconã§æå®ããã¦ãããããã¹ãã®éã¯ãããmockã§ç½®ãæãããã HogeDao hogeDao; // S2Junitãæä¾ãããã¹ãå¶å¾¡ç¨ã¤ã³ã¿ãã§ã¼ã¹ã TestContext ctx; @Before public void before() { // mockitoã§HogeDaoã®mockãçæ hogeDao=mock(HogeDao.class); // ã³ã³ãã¼ãã³ãã¨ãã¦ç»é² ctx.register(hogdDao,"hogdDao"); } @Test public test_xxx() { // 以ä¸ã®è¨å®ã«ãããmockã使ã£ããã¹ããå¯è½ã«ãªãï¼ï¼ when(hogeDao.getValue()).thenReturn(null); hogeLogic.xxx(); } }
ç¾è±¡
ãã¹ãéå§åã«HogeLogicãèªåã§DIãããããctx.register()ã§ç»é²ããä¾åã¯ã©ã¹(HogeDao)ãåæ ãã¦ãããªãã
çç±
ãã£ã¼ã«ãã¤ã³ã¸ã§ã¯ã·ã§ã³ã§ããªãã®ã¯ãS2Containerã®èªåã¤ã³ã¸ã§ã¯ã·ã§ã³æã®ã«ã¼ã«ã«ããã
S2Containerã®ããã©ã«ãå®è£ S2ContainerImplã«ããã¦S2Container#getComponentã§ã³ã³ãã¼ãã³ããåå¾ããå ´åã
- getComponentDefãå¼ã³åºãã¦ã³ã³ãã¼ãã³ãå®ç¾©(ComponentDef)ãå¾ã
- ComponentDef#getComponent()ã§ã³ã³ãã¼ãã³ããæ§ç¯ãã¦è¿ã
ãã¦ãComponentDefã®ããã©ã«ãå®è£
ComponentDefImplã«ããã¦ã¯ãã³ã³ãã¼ãã³ãçæãInstanceDefçµç±ã§ComponentDeployer#deployã«å§è²ããã®å¾ãªãã ããã ãã£ã¦ã¤ã³ã¹ã¿ã³ã¹ãæ§ç¯ãã¾ã*1ããã®å¾çæããã¤ã³ã¹ã¿ã³ã¹ã«ãã£ã¼ã«ã/ããããã£ã¤ã³ã¸ã§ã¯ã·ã§ã³ãè¡ããå®æããã¤ã³ã¹ã¿ã³ã¹ãè¿ãã¨ããæµãã«ãªãã¾ãã
ãã¦ãã¤ã³ã¹ã¿ã³ã¹çææã®ã¤ã³ã¸ã§ã¯ã·ã§ã³å¦çãåé¡ããã¨ãã°ã³ã³ã¹ãã©ã¯ã¿ã¤ã³ã¸ã§ã¯ã·ã§ã³ãè¡ãAbstractAssemblerã¯ã©ã¹ã«ããã¦ã¯ã
// AbstractAssembler.java L:86 // AbstractAssembler#getArgs args[i] = getComponentDef().getContainer().getComponent( argTypes[i]);
ã¨ããå¦çã§ã³ã³ã¹ãã©ã¯ã¿ã«æ¸¡ãä¾åã³ã³ãã¼ãã³ããè¨å®ãã¦ãã¾ããããã¦ä¾åã³ã³ãã¼ãã³ããæ¢ç´¢ãã対象ã®ã³ã³ããã¯ããæ§ç¯å¯¾è±¡ã®ã³ã³ãã¼ãã³ããå®ç¾©ãããã³ã³ããããªãã§ããã
ãã¦ãS2Junitã«ããããã¹ãã¡ã½ããã®å®è¡ã¯S2TestMethodRunner#runMethod()ã§è¡ããã¦ãã¾ãããã®ã¡ã½ããã¯ã
- setUpTestContext() ã§ã³ã³ããã¨ãã¹ãã³ã³ããã¹ãã®ä½æ
- runBefore() ã§beforeå¦çå®è¡
- initContainer() ã§ã³ã³ãããåæå(s2junit4.diconã®include)
- bindFields() ã§ãã¹ãã¯ã©ã¹ã®ãã£ã¼ã«ãã«å¯¾ãã¦DIãå®è¡
- runTest() ã§ãã¹ãã¡ã½ããå®è¡
ã¨ããæµãã«ãªã£ã¦ãã¾ãã
ãã¦ããã¹ãæã®ã³ã³ããã®æ§é ã¯ã©ããªã£ã¦ããã®ãã¨ããã¨ã
- S2TestMethodRunner#setUpTestContext ã«ããã¦ã«ã¼ãã¨ãªãã³ã³ãããä½æ
- SingletonS2Containerããã³TestContextã使ç¨ããã®ã¯ãã®ã³ã³ããã§ã
- beforeã¡ã½ããã§ã³ã³ããã«å¯¾ãã¦ä½ãæä½ããå ´åãã«ã¼ãã³ã³ããã«å¯¾ããå¦çã¨ãªãã¾ãã
- initContainer() ã§ã«ã¼ãã³ã³ããã«å¯¾ãã¦s2junit4.diconãinclude
- ãã®å¦çã«ãããs2junit4.diconã«ããè¨å®ãåæ ããã³ã³ãããä½æããããã«ã¼ãã³ã³ããã®åä¾ãã¨ãã¦ç»é²ããã¾ã
- bindFields()ã§DIå®è¡
ãã¦ãS2Containerã®ã³ã³ãã¼ãã³ãæ¢ç´¢ã«ããã¦ã¯ã
- 親ã¯åã«å®ç¾©ãããã³ã³ãã¼ãã³ããåç §ã§ãã
- åã¯è¦ªã«å®ç¾©ãããã³ã³ãã¼ãã³ããåç §ã§ããªã
ã¨ãªã£ã¦ãã¾ã(åç §: S2コンテナのインスタンス階層について)
ãããã£ã¦ãããã¹ãã³ã³ããã¹ãçµç±ã§ã«ã¼ãã³ã³ããã«å®ç¾©ããmock(HogeDao)ã³ã³ãã¼ãã³ããããs2junit4.diconã§å®ç¾©ããHogeLogicã³ã³ãã¼ãã³ãã®å±ããã³ã³ãããããåç §ãããã¨ã¯ã§ããªãããã§ããï¼ï¼ï¼
解決æ¹æ³
ä¸è¨ã®çç±ã«ããããã¹ãã¯ã©ã¹ã®ãã£ã¼ã«ãã¤ã³ã¸ã§ã¯ã·ã§ã³åã«è¨å®ããã³ã³ãã¼ãã³ããåæ ãããã®ã¯ä¸å¯è½ã£ã½ãã
S2Containerã®ã³ã³ãã¼ãã³ãã«ãã¯ã¢ããã®æåã¯S2ContainerBehavior.setProviderã使ã£ã¦ããã¯ãããã¨ãã§ããããã®æ©æ§ã使ã£ã¦ãä¸æçã«ä¸æ¸ãç¨ã®å®ç¾©ãæåªå ã§è¦ã«è¡ãããã«ããã
// ä¸æ¸ããããã³ã³ãã¼ãã³ããå®ç¾©ããã³ã³ãã private S2Container containerForOverride; public <T> T getComponent(Class<T> componentClass) { S2ContainerBehavior .setProvider(new S2ContainerBehavior.DefaultProvider() { @Override public ComponentDef acquireFromGetComponent( S2Container container, Object key) { if (containerForOverride.hasComponentDef(key)) return containerForOverride.getComponentDef(key); else return super .acquireFromGetComponent(container, key); } }); final T component = componentClass.cast(SingletonS2Container .getComponent(componentClass)); S2ContainerBehavior .setProvider(new S2ContainerBehavior.DefaultProvider()); return component; } // ã³ã³ãã¼ãã³ãåå¾æã¯ãèªåãã£ã¼ã«ãã¤ã³ã¸ã§ã¯ã·ã§ã³ãSingletonS2Containerã使ç¨ãã // getComponentçµç±ã§åå¾ããã
å¤ãã³ã¼ã(ä¸å¿æ®ãã¨ããã©ç¡é§ã«è¤éãªãã¨ãã£ã¦ãã®ã§ä½¿ããªãã»ããããã§ãã)
試è¡é¯èª¤ã®çµæããããªã³ã¼ããæ¸ããã
/** ãã®ã³ã³ããã«ç»é²ãããã³ã³ãã¼ãã³ãã¯ãé常ã®DIè¨å®ãä¸æ¸ããã */ final S2Container containerForOverride = new S2ContainerImpl(); /** * æå®ããã¯ã©ã¹ã®ã¢ãã¯ãä½æããã³ã³ããã«ç»é²ãã¦ããè¿ã * * @param <T> * 対象ã®å * @param targetClass * 対象ã®ã¯ã©ã¹ * @return ã¢ãã¯ãããã³ã³ããã«ç»é²ããããªãã¸ã§ã¯ã */ private <T> T mockAndRegister(Class<T> targetClass) { final T mocked = mock(targetClass); containerForOverride.register(mocked, targetClass.getSimpleName()); return mocked; } public <T> T getComponent(Class<T> componentClass) { // ãã¹ãç°å¢ã使ç¨ãã¦ããã«ã¼ãã®S2Containerãåå¾ final S2Container root = SingletonS2ContainerFactory.getContainer(); // çæ対象ã³ã³ãã¼ãã³ãã®å®ç¾©ãã«ã¼ãã³ã³ããããåå¾ final ComponentDef def = root.getComponentDef(componentClass); // çææã«ä¾åã³ã³ãã¼ãã³ãã解決ããã®ã«ä½¿ãããã®ã¯ãã³ã³ãã¼ãã³ãå®ç¾©ãææããã³ã³ããã // çæ対象ã³ã³ãã¼ãã³ãããã³ãã®ä¾åã³ã³ãã¼ãã³ãã使ç¨ããã³ã³ãããã // ãå ã®ã³ã³ãããã¨ãä¸æ¸ãç¨ã³ã³ããããåæããã³ã³ããã«å¤æ´ overrideContainer(root); // ã³ã³ãã¼ãã³ããçæãã¦è¿ã return componentClass.cast(def.getComponent()); } private void overrideContainer(S2Container root) { System.err.println(root.getNamespace()); final S2Container newContainer = new S2ContainerImpl(); newContainer.include(containerForOverride); newContainer.include(root); final List<ComponentDef> defs = Lists.newArrayList(); for (int i = 0; i < root.getComponentDefSize(); i++) defs.add(root.getComponentDef(i)); for (ComponentDef cd : defs) { cd.setContainer(newContainer); System.err.println(cd.getComponentName()); } final List<S2Container> children = Lists.newArrayList(); for (int i = 0; i < root.getChildSize(); i++) children.add(root.getChild(i)); for (S2Container c : children) overrideContainer(c); }
@Test public void test() { final HogeDao mocked=mockAndRegister(HogeDao.class); final HogeLogic target=getComponent(HogeLogic.class); when(mocked).doSomething().thenReturn(0); assertThat(target.doSomething(), is(0)); // ... }
ã¨ããããã§ããã£ãã®ã³ã¼ãã§ã¯åã³ã³ãã¼ãã³ãå®ç¾©ãåç §ããã³ã³ããããä¸æ¸ã対象ã®ã³ã³ãã¼ãã³ããåªå çã«æ¤ç´¢ããã³ã³ãããã«å¤æ´ãããã¨ã§ã©ãã«ãããã®ã§ããã
*1:詳細ã«ã¤ãã¦ã¯ãçæ対象ã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã«ãã¬ã¼ã¯ãã¤ã³ãå¼µã£ã¦ãããã¬ã§ã¹ã¿ãã¯ãã¬ã¼ã¹çºããã¨ããããããã§ã