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 }