[
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)