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     */
027    public class AbstractComponentMonitorTestCase extends MockObjectTestCase {
028    
029        public void testDelegatingMonitorThrowsExpectionWhenConstructionWithNullDelegate(){
030            try {
031                new AbstractComponentMonitor(null);
032                fail("NPE expected");
033            } catch (NullPointerException e) {
034                assertEquals("NPE", "monitor", e.getMessage());
035            }
036        }
037    
038        public void testDelegatingMonitorThrowsExpectionWhenChangingToNullMonitor(){
039            AbstractComponentMonitor dcm = new AbstractComponentMonitor();
040            try {
041                dcm.changeMonitor(null);
042                fail("NPE expected");
043            } catch (NullPointerException e) {
044                assertEquals("NPE", "monitor", e.getMessage());
045            }
046        }
047    
048        public void testDelegatingMonitorCanChangeMonitorInDelegateThatDoesSupportMonitorStrategy() {
049            ComponentMonitor monitor = mockMonitorWithNoExpectedMethods();
050            AbstractComponentMonitor dcm = new AbstractComponentMonitor(mockMonitorThatSupportsStrategy(monitor));
051            dcm.changeMonitor(monitor);
052            assertEquals(monitor, dcm.currentMonitor());
053            dcm.instantiating(null, null, null);
054        }
055    
056        public void testDelegatingMonitorChangesDelegateThatDoesNotSupportMonitorStrategy() {
057            ComponentMonitor delegate = mockMonitorWithNoExpectedMethods();
058            AbstractComponentMonitor dcm = new AbstractComponentMonitor(delegate);
059            ComponentMonitor monitor = mockMonitorWithNoExpectedMethods();
060            assertEquals(delegate, dcm.currentMonitor());
061            dcm.changeMonitor(monitor);
062            assertEquals(monitor, dcm.currentMonitor());
063        }
064    
065        public void testDelegatingMonitorReturnsDelegateThatDoesNotSupportMonitorStrategy() {
066            ComponentMonitor delegate = mockMonitorWithNoExpectedMethods();
067            AbstractComponentMonitor dcm = new AbstractComponentMonitor(delegate);
068            assertEquals(delegate, dcm.currentMonitor());
069        }
070    
071        private ComponentMonitor mockMonitorWithNoExpectedMethods() {
072            Mock mock = mock(ComponentMonitor.class);
073            return (ComponentMonitor)mock.proxy();
074        }
075    
076        private ComponentMonitor mockMonitorThatSupportsStrategy(ComponentMonitor currentMonitor) {
077            Mock mock = mock(TestMonitorThatSupportsStrategy.class);
078            mock.expects(once()).method("changeMonitor").with(eq(currentMonitor));
079            mock.expects(once()).method("currentMonitor").withAnyArguments().will(returnValue(currentMonitor));
080            mock.expects(once()).method("instantiating").withAnyArguments();
081            return (ComponentMonitor)mock.proxy();
082        }
083    
084        public void testMonitoringHappensBeforeAndAfterInstantiation() throws NoSuchMethodException {
085            final Vector ourIntendedInjectee0 = new Vector();
086            final String ourIntendedInjectee1 = "hullo";
087            DefaultPicoContainer parent = new DefaultPicoContainer();
088            Mock monitor = mock(ComponentMonitor.class);
089            DefaultPicoContainer child = new DefaultPicoContainer(new AbstractComponentMonitor((ComponentMonitor) monitor.proxy()), parent);
090    
091            Constructor nacotCtor = NeedsACoupleOfThings.class.getConstructors()[0];
092            monitor.expects(once()).method("instantiating").with(same(child), isA(ConstructorInjector.class), eq(nacotCtor)).will(returnValue(nacotCtor));
093            Constraint durationIsGreaterThanOrEqualToZero = new Constraint() {
094                public boolean eval(Object o) {
095                    Long duration = (Long)o;
096                    return 0 <= duration;
097                }
098    
099                public StringBuffer describeTo(StringBuffer stringBuffer) {
100                    return stringBuffer.append("The endTime wasn't after the startTime");
101                }
102            };
103            Constraint isANACOTThatWozCreated = new Constraint() {
104                public boolean eval(Object o) {
105                    return o instanceof NeedsACoupleOfThings;
106                }
107    
108                public StringBuffer describeTo(StringBuffer stringBuffer) {
109                    return stringBuffer.append("Should have been a hashmap");
110                }
111            };
112            Constraint collectionAndStringWereInjected = new Constraint() {
113                public boolean eval(Object o) {
114                    Object[] ctorArgs = (Object[]) o;
115                    return ctorArgs.length == 2 && ctorArgs[0] == ourIntendedInjectee0 && ctorArgs[1] == ourIntendedInjectee1;
116                }
117                public StringBuffer describeTo(StringBuffer stringBuffer) {
118                    return stringBuffer.append("Should have injected our intended vector and string");
119                }
120            };
121            monitor.expects(once()).method("instantiated").with(new Constraint[] {same(child), isA(ConstructorInjector.class),eq(nacotCtor), isANACOTThatWozCreated, collectionAndStringWereInjected, durationIsGreaterThanOrEqualToZero});
122            parent.addComponent(ourIntendedInjectee0);
123            parent.addComponent(ourIntendedInjectee1);
124            child.addComponent(NeedsACoupleOfThings.class);
125            child.getComponent(NeedsACoupleOfThings.class);
126        }
127    
128        public static class NeedsACoupleOfThings {
129            public NeedsACoupleOfThings(Collection collection, String string) {
130            }
131        }
132    
133        public static interface TestMonitorThatSupportsStrategy extends ComponentMonitor, ComponentMonitorStrategy {
134        }
135    }