001    /*****************************************************************************
002     * Copyright (C) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the LICENSE.txt file.                                                     *
007     *                                                                           *
008     * Original code by                                                          *
009     *****************************************************************************/
010    package org.picocontainer.defaults;
011    
012    import org.jmock.Mock;
013    import org.jmock.MockObjectTestCase;
014    import org.jmock.core.Constraint;
015    import org.picocontainer.ComponentMonitor;
016    import org.picocontainer.ComponentMonitorStrategy;
017    import org.picocontainer.DefaultPicoContainer;
018    import org.picocontainer.injectors.ConstructorInjector;
019    import org.picocontainer.monitors.AbstractComponentMonitor;
020    
021    import java.lang.reflect.Constructor;
022    import java.util.*;
023    
024    /**
025     * @author Mauro Talevi
026     * @version $Revision: 2200 $
027     */
028    public class AbstractComponentMonitorTestCase extends MockObjectTestCase {
029    
030        public void testDelegatingMonitorThrowsExpectionWhenConstructionWithNullDelegate(){
031            try {
032                new AbstractComponentMonitor(null);
033                fail("NPE expected");
034            } catch (NullPointerException e) {
035                assertEquals("NPE", "monitor", e.getMessage());
036            }
037        }
038    
039        public void testDelegatingMonitorThrowsExpectionWhenChangingToNullMonitor(){
040            AbstractComponentMonitor dcm = new AbstractComponentMonitor();
041            try {
042                dcm.changeMonitor(null);
043                fail("NPE expected");
044            } catch (NullPointerException e) {
045                assertEquals("NPE", "monitor", e.getMessage());
046            }
047        }
048    
049        public void testDelegatingMonitorCanChangeMonitorInDelegateThatDoesSupportMonitorStrategy() {
050            ComponentMonitor monitor = mockMonitorWithNoExpectedMethods();
051            AbstractComponentMonitor dcm = new AbstractComponentMonitor(mockMonitorThatSupportsStrategy(monitor));
052            dcm.changeMonitor(monitor);
053            assertEquals(monitor, dcm.currentMonitor());
054            dcm.instantiating(null, null, null);
055        }
056    
057        public void testDelegatingMonitorChangesDelegateThatDoesNotSupportMonitorStrategy() {
058            ComponentMonitor delegate = mockMonitorWithNoExpectedMethods();
059            AbstractComponentMonitor dcm = new AbstractComponentMonitor(delegate);
060            ComponentMonitor monitor = mockMonitorWithNoExpectedMethods();
061            assertEquals(delegate, dcm.currentMonitor());
062            dcm.changeMonitor(monitor);
063            assertEquals(monitor, dcm.currentMonitor());
064        }
065    
066        public void testDelegatingMonitorReturnsDelegateThatDoesNotSupportMonitorStrategy() {
067            ComponentMonitor delegate = mockMonitorWithNoExpectedMethods();
068            AbstractComponentMonitor dcm = new AbstractComponentMonitor(delegate);
069            assertEquals(delegate, dcm.currentMonitor());
070        }
071    
072        private ComponentMonitor mockMonitorWithNoExpectedMethods() {
073            Mock mock = mock(ComponentMonitor.class);
074            return (ComponentMonitor)mock.proxy();
075        }
076    
077        private ComponentMonitor mockMonitorThatSupportsStrategy(ComponentMonitor currentMonitor) {
078            Mock mock = mock(TestMonitorThatSupportsStrategy.class);
079            mock.expects(once()).method("changeMonitor").with(eq(currentMonitor));
080            mock.expects(once()).method("currentMonitor").withAnyArguments().will(returnValue(currentMonitor));
081            mock.expects(once()).method("instantiating").withAnyArguments();
082            return (ComponentMonitor)mock.proxy();
083        }
084    
085        public void testMonitoringHappensBeforeAndAfterInstantiation() throws NoSuchMethodException {
086            final Vector ourIntendedInjectee0 = new Vector();
087            final String ourIntendedInjectee1 = "hullo";
088            DefaultPicoContainer parent = new DefaultPicoContainer();
089            Mock monitor = mock(ComponentMonitor.class);
090            DefaultPicoContainer child = new DefaultPicoContainer(new AbstractComponentMonitor((ComponentMonitor) monitor.proxy()), parent);
091    
092            Constructor nacotCtor = NeedsACoupleOfThings.class.getConstructors()[0];
093            monitor.expects(once()).method("instantiating").with(same(child), isA(ConstructorInjector.class), eq(nacotCtor)).will(returnValue(nacotCtor));
094            Constraint durationIsGreaterThanOrEqualToZero = new Constraint() {
095                public boolean eval(Object o) {
096                    Long duration = (Long)o;
097                    return 0 <= duration;
098                }
099    
100                public StringBuffer describeTo(StringBuffer stringBuffer) {
101                    return stringBuffer.append("The endTime wasn't after the startTime");
102                }
103            };
104            Constraint isANACOTThatWozCreated = new Constraint() {
105                public boolean eval(Object o) {
106                    return o instanceof NeedsACoupleOfThings;
107                }
108    
109                public StringBuffer describeTo(StringBuffer stringBuffer) {
110                    return stringBuffer.append("Should have been a hashmap");
111                }
112            };
113            Constraint collectionAndStringWereInjected = new Constraint() {
114                public boolean eval(Object o) {
115                    Object[] ctorArgs = (Object[]) o;
116                    return ctorArgs.length == 2 && ctorArgs[0] == ourIntendedInjectee0 && ctorArgs[1] == ourIntendedInjectee1;
117                }
118                public StringBuffer describeTo(StringBuffer stringBuffer) {
119                    return stringBuffer.append("Should have injected our intended vector and string");
120                }
121            };
122            monitor.expects(once()).method("instantiated").with(new Constraint[] {same(child), isA(ConstructorInjector.class),eq(nacotCtor), isANACOTThatWozCreated, collectionAndStringWereInjected, durationIsGreaterThanOrEqualToZero});
123            parent.addComponent(ourIntendedInjectee0);
124            parent.addComponent(ourIntendedInjectee1);
125            child.addComponent(NeedsACoupleOfThings.class);
126            child.getComponent(NeedsACoupleOfThings.class);
127        }
128    
129        public static class NeedsACoupleOfThings {
130            public NeedsACoupleOfThings(Collection collection, String string) {
131            }
132        }
133    
134        public static interface TestMonitorThatSupportsStrategy extends ComponentMonitor, ComponentMonitorStrategy {
135        }
136    }