001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.proxy.invoker;
019    
020    import junit.framework.TestCase;
021    import org.apache.commons.proxy.ObjectProvider;
022    import org.apache.commons.proxy.ProxyFactory;
023    import org.apache.commons.proxy.provider.ConstantProvider;
024    
025    import java.io.Serializable;
026    
027    /**
028     *
029     */
030    public class TestDuckTypingInvoker extends TestCase
031    {
032    //----------------------------------------------------------------------------------------------------------------------
033    // Other Methods
034    //----------------------------------------------------------------------------------------------------------------------
035    
036        public void testExactSignatureMatch()
037        {
038            final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
039            final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
040            final Duck duck = ( Duck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{ Duck.class } );
041            assertEquals( "Quack!", duck.sayQuack() );
042        }
043    
044        public void testNoMatchingMethod()
045        {
046            final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
047            final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
048            final Goose goose = ( Goose ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{ Goose.class } );
049            try
050            {
051                goose.sayHonk();
052                fail( "No matching method should be found." );
053            }
054            catch ( UnsupportedOperationException e )
055            {
056                // Do nothing, expected behavior!
057            }
058        }
059    
060        public void testMismatchingParameterType()
061        {
062            final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
063            final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
064            final ParameterizedDuck parameterizedDuck = ( ParameterizedDuck ) new ProxyFactory()
065                    .createInvokerProxy( invoker, new Class[]{ ParameterizedDuck.class } );
066            try
067            {
068                parameterizedDuck.sayQuack("Elmer");
069                fail( "No matching method should be found." );
070            }
071            catch ( UnsupportedOperationException e )
072            {
073                // Do nothing, expected behavior!
074            }
075        }
076    
077        public void testTargetHasCompatibleReturnType()
078        {
079            final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
080            final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
081            final SerializableDuck duck = ( SerializableDuck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{
082                    SerializableDuck.class } );
083            assertEquals("Quack!", duck.sayQuack() );
084    
085        }
086    
087        public void testMismatchingReturnType()
088        {
089            final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
090            final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
091            final VoidReturnDuck voidDuck = ( VoidReturnDuck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{
092                    VoidReturnDuck.class } );
093            try
094            {
095                voidDuck.sayQuack();
096                fail( "No matching method should be found." );
097            }
098            catch ( UnsupportedOperationException e )
099            {
100                // Do nothing, expected behavior!
101            }
102        }
103    
104    //----------------------------------------------------------------------------------------------------------------------
105    // Inner Classes
106    //----------------------------------------------------------------------------------------------------------------------
107    
108        public static class LegacyDuck
109        {
110            public String sayQuack()
111            {
112                return "Quack!";
113            }
114        }
115    
116        public interface Duck
117        {
118            public String sayQuack();
119        }
120    
121        public interface SerializableDuck
122        {
123            public Serializable sayQuack();
124        }
125        
126        public interface ParameterizedDuck
127        {
128            public String sayQuack( String recipient );
129        }
130    
131        public interface VoidReturnDuck
132        {
133            public void sayQuack();
134        }
135    
136        public interface Goose
137        {
138            public void sayHonk();
139        }
140    }