diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java index 9ee1e396d8..e6147da7f8 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java @@ -17,6 +17,7 @@ package org.apache.dubbo.rpc.cluster.support.wrapper; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.CollectionUtils; @@ -24,6 +25,7 @@ import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.AsyncRpcResult; import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.InvokeMode; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; import org.apache.dubbo.rpc.RpcContext; @@ -31,7 +33,9 @@ import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.cluster.ClusterInvoker; import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.protocol.dubbo.FutureAdapter; import org.apache.dubbo.rpc.support.MockInvoker; +import org.apache.dubbo.rpc.support.RpcUtils; import java.util.List; @@ -42,6 +46,7 @@ import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK; public class MockClusterInvoker implements ClusterInvoker { private static final Logger logger = LoggerFactory.getLogger(MockClusterInvoker.class); + private static final boolean setFutureWhenSync = Boolean.parseBoolean(System.getProperty(CommonConstants.SET_FUTURE_IN_SYNC_MODE, "true")); private final Directory directory; @@ -135,6 +140,9 @@ public class MockClusterInvoker implements ClusterInvoker { Result result; Invoker mockInvoker; + RpcInvocation rpcInvocation = (RpcInvocation)invocation; + rpcInvocation.setInvokeMode(RpcUtils.getInvokeMode(getUrl(),invocation)); + List> mockInvokers = selectMockInvoker(invocation); if (CollectionUtils.isEmpty(mockInvokers)) { mockInvoker = (Invoker) new MockInvoker(getUrl(), directory.getInterface()); @@ -152,6 +160,10 @@ public class MockClusterInvoker implements ClusterInvoker { } catch (Throwable me) { throw new RpcException(getMockExceptionMessage(e, me), me.getCause()); } + if (setFutureWhenSync || rpcInvocation.getInvokeMode() != InvokeMode.SYNC) { + // set server context + RpcContext.getServiceContext().setFuture(new FutureAdapter<>(((AsyncRpcResult)result).getResponseFuture())); + } return result; } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java index aceec90f6c..6b5745e706 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvokerTest.java @@ -37,6 +37,8 @@ import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY; @@ -157,6 +159,9 @@ public class MockClusterInvokerTest { invocation.setMethodName("sayHello"); ret = cluster.invoke(invocation); Assertions.assertNull(ret.getValue()); + + + } @Test @@ -589,6 +594,29 @@ public class MockClusterInvokerTest { Result ret = cluster.invoke(invocation); Assertions.assertEquals(0, ((List) ret.getValue()).size()); } + @Test + public void testMockInvokerFromOverride_Invoke_check_ListPojoAsync() throws ExecutionException, InterruptedException { + URL url = URL.valueOf("remote://1.2.3.4/" + IHelloService.class.getName()) + .addParameter(REFER_KEY, + URL.encode(PATH_KEY + "=" + IHelloService.class.getName() + + "&" + "getUsersAsync.mock=force")) + .addParameter("invoke_return_error", "true"); + Invoker cluster = getClusterInvoker(url); + //Configured with mock + RpcInvocation invocation = new RpcInvocation(); + invocation.setMethodName("getUsersAsync"); + invocation.setReturnType(CompletableFuture.class); + Result ret = cluster.invoke(invocation); + CompletableFuture> cf = null; + try { + cf = (CompletableFuture>) ret.recreate(); + } catch (Throwable e) { + e.printStackTrace(); + } + Assertions.assertEquals(2, cf.get().size()); + Assertions.assertEquals("Tommock", cf.get().get(0).getName()); + } + @SuppressWarnings("unchecked") @Test @@ -753,6 +781,8 @@ public class MockClusterInvokerTest { List getUsers(); + CompletableFuture> getUsersAsync(); + void sayHello(); } @@ -793,6 +823,13 @@ public class MockClusterInvokerTest { return Arrays.asList(new User[]{new User(1, "Tom"), new User(2, "Jerry")}); } + @Override + public CompletableFuture> getUsersAsync() { + CompletableFuture> cf=new CompletableFuture<>(); + cf.complete(Arrays.asList(new User[]{new User(1, "Tom"), new User(2, "Jerry")})); + return cf; + } + public void sayHello() { System.out.println("hello prety"); } @@ -827,6 +864,13 @@ public class MockClusterInvokerTest { return Arrays.asList(new User[]{new User(1, "Tommock"), new User(2, "Jerrymock")}); } + @Override + public CompletableFuture> getUsersAsync() { + CompletableFuture> cf=new CompletableFuture<>(); + cf.complete(Arrays.asList(new User[]{new User(1, "Tommock"), new User(2, "Jerrymock")})); + return cf; + } + public int getInt1() { return 1; }