[ 
https://issues.apache.org/jira/browse/CAMEL-16658?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen resolved CAMEL-16658.
---------------------------------
    Resolution: Fixed

Thanks for reporting and providing a patch with tests

> AmbiguousMethodCallException when using Mockito mock as bean for camel-bean 
> component.
> --------------------------------------------------------------------------------------
>
>                 Key: CAMEL-16658
>                 URL: https://issues.apache.org/jira/browse/CAMEL-16658
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-bean
>    Affects Versions: 3.x
>            Reporter: Krzysztof Mackowiak
>            Assignee: Claus Ibsen
>            Priority: Minor
>             Fix For: 3.11.0
>
>         Attachments: 
> Fix_-_AmbiguousMethodCallException_when_using_Mockito_mock_as_bean_for_camel-bean_componen.patch,
>  
> Tests_-_AmbiguousMethodCallException_when_using_Mockito_mock_as_bean_for_camel-bean_compon.patch
>
>
> In Camel 2.x camel-bean component considered only public methods when trying 
> to choose a method to call.
> In Camel 3.x this behaviour was changed and now protected and package methods 
> are also considered (it was implemented in the CAMEL-13298 task).
> Unfortunately this change causes that using Mockito mocks as beans for 
> camel-bean components (for example to test some Camel routes) causes an 
> AmbiguousMethodCallException to be thrown.
> Here is an example of such exception:
> {code:java}
> org.apache.camel.component.bean.AmbiguousMethodCallException: Ambiguous 
> method invocations possible:
> [public java.lang.String 
> org.apache.camel.component.bean.MockitoMockForClassTest$MyService$MockitoMock$1368359973.doSomething(java.lang.String),
> final java.lang.String 
> org.apache.camel.component.bean.MockitoMockForClassTest$MyService$MockitoMock$1368359973.doSomething$accessor$MJMz0OHK(java.lang.String)]
> on the exchange: Exchange[]
>   at 
> org.apache.camel.component.bean.BeanInfo.chooseBestPossibleMethodInfo(BeanInfo.java:887)
>   ...
> {code}
>  
> This is caused by the fact that Mockito adds package level methods with the 
> same argument list to created mock/spy.
> Additional complication is added by the fact that Mockito 1.x (which uses 
> CGLIB underneath) adds different methods than Mockito 2.x and 3.x (which uses 
> Byte Buddy).
> Here are 3 JUnit tests that reproduce this problem:
> {code:java}
> // NOTE: fails for Mockito 3.x and 2.x, but passes for Mockito 1.x
> public class MockitoMockForClassTest extends ContextTestSupport {
>     @Test
>     public void testCallingMock() throws Exception {
>         Object response = template.requestBody("direct:start", "anything");
>         assertEquals("mocked answer", response);
>     }
>     @Override
>     protected Registry createRegistry() throws Exception {
>         MyService mockService = Mockito.mock(MyService.class);
>         when(mockService.doSomething(any())).thenReturn("mocked answer");
>         Registry answer = super.createRegistry();
>         answer.bind("myService", mockService);
>         return answer;
>     }
>     @Override
>     protected RouteBuilder createRouteBuilder() throws Exception {
>         return new RouteBuilder() {
>             public void configure() throws Exception {
>                 from("direct:start").bean("bean:myService");
>             }
>         };
>     }
>     public class MyService {
>         public String doSomething(String body) {
>             return "real answer";
>         }
>     }
> }
> {code}
> {code:java}
> // NOTE: fails for Mockito 3.x and 2.x, but passes for Mockito 1.x
> public class MockitoSpyForClassTest extends ContextTestSupport {
>     @Test
>     public void testCallingSpy() throws Exception {
>         Object response = template.requestBody("direct:start", "anything");
>         assertEquals("mocked answer", response);
>     }
>     @Override
>     protected Registry createRegistry() throws Exception {
>         MyService mockService = Mockito.spy(new MyService());
>         when(mockService.doSomething(any())).thenReturn("mocked answer");
>         Registry answer = super.createRegistry();
>         answer.bind("myService", mockService);
>         return answer;
>     }
>     @Override
>     protected RouteBuilder createRouteBuilder() throws Exception {
>         return new RouteBuilder() {
>             public void configure() throws Exception {
>                 from("direct:start").bean("bean:myService");
>             }
>         };
>     }
>     public class MyService {
>         public String doSomething(String body) {
>             return "real answer";
>         }
>     }
> }
> {code}
> {code:java}
> // NOTE: fails for Mockito 1.x, but passes for Mockito 3.x and 2.x
> public class MockitoMockForInterfaceTest extends ContextTestSupport {
>     @Test
>     public void testCallingMock() throws Exception {
>         Object response = template.requestBody("direct:start", "anything");
>         assertEquals("mocked answer", response);
>     }
>     @Override
>     protected Registry createRegistry() throws Exception {
>         MyService mockService = Mockito.mock(MyService.class);
>         when(mockService.doSomething(any())).thenReturn("mocked answer");
>         Registry answer = super.createRegistry();
>         answer.bind("myService", mockService);
>         return answer;
>     }
>     @Override
>     protected RouteBuilder createRouteBuilder() throws Exception {
>         return new RouteBuilder() {
>             public void configure() throws Exception {
>                 from("direct:start").bean("bean:myService");
>             }
>         };
>     }
>     public interface MyService {
>         String doSomething(String body);
>     }
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to