    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 static org.junit.Assert.assertEquals;
    013    import static org.junit.Assert.fail;
    014    import static org.picocontainer.tck.MockFactory.mockeryWithCountingNamingScheme;
    015
    016    import java.lang.reflect.Constructor;
    017    import java.util.Collection;
    018    import java.util.Vector;
    019
    020    import org.hamcrest.BaseMatcher;
    021    import org.hamcrest.Description;
    022    import org.hamcrest.Matcher;
    023    import org.jmock.Expectations;
    024    import org.jmock.Mockery;
    025    import org.jmock.integration.junit4.JMock;
    026    import org.junit.Test;
    027    import org.junit.runner.RunWith;
    028    import org.picocontainer.ComponentAdapter;
    029    import org.picocontainer.ComponentMonitor;
    030    import org.picocontainer.ComponentMonitorStrategy;
    031    import org.picocontainer.DefaultPicoContainer;
    032    import org.picocontainer.PicoContainer;
    033    import org.picocontainer.injectors.ConstructorInjector;
    034    import org.picocontainer.monitors.AbstractComponentMonitor;
    035
    036    /**
    037     * @author Mauro Talevi
    038     */
    039    @RunWith(JMock.class)
    040    public class AbstractComponentMonitorTestCase {
    041
    042            private Mockery mockery = mockeryWithCountingNamingScheme();
    043
    044        @Test public void testDelegatingMonitorThrowsExpectionWhenConstructionWithNullDelegate(){
    045            try {
    046                new AbstractComponentMonitor(null);
    047                fail("NPE expected");
    048            } catch (NullPointerException e) {
    049                assertEquals("NPE", "monitor", e.getMessage());
    050            }
    051        }
    052
    053        @Test public void testDelegatingMonitorThrowsExpectionWhenChangingToNullMonitor(){
    054            AbstractComponentMonitor dcm = new AbstractComponentMonitor();
    055            try {
    056                dcm.changeMonitor(null);
    057                fail("NPE expected");
    058            } catch (NullPointerException e) {
    059                assertEquals("NPE", "monitor", e.getMessage());
    060            }
    061        }
    062
    063        @Test public void testDelegatingMonitorCanChangeMonitorInDelegateThatDoesSupportMonitorStrategy() {
    064            ComponentMonitor monitor = mockMonitorWithNoExpectedMethods();
    065            AbstractComponentMonitor dcm = new AbstractComponentMonitor(mockMonitorThatSupportsStrategy(monitor));
    066            dcm.changeMonitor(monitor);
    067            assertEquals(monitor, dcm.currentMonitor());
    068            dcm.instantiating(null, null, null);
    069        }
    070
    071        @Test public void testDelegatingMonitorChangesDelegateThatDoesNotSupportMonitorStrategy() {
    072            ComponentMonitor delegate = mockMonitorWithNoExpectedMethods();
    073            AbstractComponentMonitor dcm = new AbstractComponentMonitor(delegate);
    074            ComponentMonitor monitor = mockMonitorWithNoExpectedMethods();
    075            assertEquals(delegate, dcm.currentMonitor());
    076            dcm.changeMonitor(monitor);
    077            assertEquals(monitor, dcm.currentMonitor());
    078        }
    079
    080        @Test public void testDelegatingMonitorReturnsDelegateThatDoesNotSupportMonitorStrategy() {
    081            ComponentMonitor delegate = mockMonitorWithNoExpectedMethods();
    082            AbstractComponentMonitor dcm = new AbstractComponentMonitor(delegate);
    083            assertEquals(delegate, dcm.currentMonitor());
    084        }
    085
    086        private ComponentMonitor mockMonitorWithNoExpectedMethods() {
    087            return mockery.mock(ComponentMonitor.class);
    088        }
    089
    090        private ComponentMonitor mockMonitorThatSupportsStrategy(final ComponentMonitor currentMonitor) {
    091            final TestMonitorThatSupportsStrategy monitor = mockery.mock(TestMonitorThatSupportsStrategy.class);
    092            mockery.checking(new Expectations(){{
    093                one(monitor).changeMonitor(with(equal(currentMonitor)));
    094                one(monitor).currentMonitor();
    095                will(returnValue(currentMonitor));
    096                one(monitor).instantiating(with(any(PicoContainer.class)), with(any(ComponentAdapter.class)), with(any(Constructor.class)));
    097            }});
    098            return monitor;
    099        }
    100
    101        @Test public void testMonitoringHappensBeforeAndAfterInstantiation() throws NoSuchMethodException {
    102            final Vector ourIntendedInjectee0 = new Vector();
    103            final String ourIntendedInjectee1 = "hullo";
    104            final DefaultPicoContainer parent = new DefaultPicoContainer();
    105            final ComponentMonitor monitor = mockery.mock(ComponentMonitor.class);
    106            final DefaultPicoContainer child = new DefaultPicoContainer(new AbstractComponentMonitor(monitor), parent);
    107            final Constructor needsACoupleOfThings = NeedsACoupleOfThings.class.getConstructors()[0];
    108            final Matcher<Long> durationIsGreaterThanOrEqualToZero = new BaseMatcher<Long>() {
    109                            public boolean matches(Object item) {
    110                    Long duration = (Long)item;
    111                    return 0 <= duration;
    112                            }
    113
    114                            public void describeTo(Description description) {
    115                                    description.appendText("The endTime wasn't after the startTime");
    116                            }
    117            };
    118            final Matcher<Object> isANACOTThatWozCreated = new BaseMatcher<Object>() {
    119                            public boolean matches(Object item) {
    120                    return item instanceof NeedsACoupleOfThings;
    121                            }
    122
    123                            public void describeTo(Description description) {
    124                                    description.appendText("Should have been a NeedsACoupleOfThings");
    125                            }
    126            };
    127            final Matcher<Object[]> collectionAndStringWereInjected = new BaseMatcher<Object[]>() {
    128                            public boolean matches(Object item) {
    129                                     Object[] args = (Object[]) item;
    130                                     return args.length == 2 && args[0] == ourIntendedInjectee0 && args[1] == ourIntendedInjectee1;
    131                            }
    132                            public void describeTo(Description description) {
    133                                    description.appendText("Should have injected our intended vector and string");
    134                            }
    135            };
    136            mockery.checking(new Expectations(){{
    137                    one(monitor).instantiating(with(same(child)), with(any(ConstructorInjector.class)), with(equal(needsACoupleOfThings)));
    138                    will(returnValue(needsACoupleOfThings));
    139                    one(monitor).instantiated(with(same(child)), with(any(ConstructorInjector.class)), with(equal(needsACoupleOfThings)), with(isANACOTThatWozCreated), with(collectionAndStringWereInjected), with(durationIsGreaterThanOrEqualToZero));
    140                atLeast(2).of(monitor).noComponentFound(with(any(DefaultPicoContainer.class)), with(any(Object.class)));
    141                will(returnValue(null));
    142            }});
    143            parent.addComponent(ourIntendedInjectee0);
    144            parent.addComponent(ourIntendedInjectee1);
    145            child.addComponent(NeedsACoupleOfThings.class);
    146            child.getComponent(NeedsACoupleOfThings.class);
    147        }
    148
    149        public static class NeedsACoupleOfThings {
    150            public NeedsACoupleOfThings(Collection collection, String string) {
    151            }
    152        }
    153
    154        public static interface TestMonitorThatSupportsStrategy extends ComponentMonitor, ComponentMonitorStrategy {
    155        }
    156    }