@Override
    public Result invoke(Invocation invocation) throws RpcException {
        Result result;

        String value = getUrl().getMethodParameter(
                        RpcUtils.getMethodName(invocation), MOCK_KEY, Boolean.FALSE.toString())
                .trim();
        if (ConfigUtils.isEmpty(value)) {
            // no mock
            result = this.invoker.invoke(invocation);
        } else if (value.startsWith(FORCE_KEY)) {
            if (logger.isWarnEnabled()) {
                logger.warn(
                        CLUSTER_FAILED_MOCK_REQUEST,
                        "force mock",
                        "",
                        "force-mock: " + RpcUtils.getMethodName(invocation) + " force-mock enabled , url : "
                                + getUrl());
            }
            // force:direct mock
            result = doMockInvoke(invocation, null);
        } else {
            // fail-mock
            try {
                result = this.invoker.invoke(invocation);

                // fix:#4585
                if (result.getException() != null && result.getException() instanceof RpcException) {
                    RpcException rpcException = (RpcException) result.getException();
                    if (rpcException.isBiz()) {
                        throw rpcException;
                    } else {
                        result = doMockInvoke(invocation, rpcException);
                    }
                }

            } catch (RpcException e) {
                if (e.isBiz()) {
                    throw e;
                }

                if (logger.isWarnEnabled()) {
                    logger.warn(
                            CLUSTER_FAILED_MOCK_REQUEST,
                            "failed to mock invoke",
                            "",
                            "fail-mock: " + RpcUtils.getMethodName(invocation) + " fail-mock enabled , url : "
                                    + getUrl(),
                            e);
                }
                result = doMockInvoke(invocation, e);
            }
        }
        return result;
    }
@Test
    void testMockInvokerInvoke_normal() {
        URL url = URL.valueOf("remote://1.2.3.4/" + IHelloService.class.getName());
        url = url.addParameter(
                REFER_KEY, URL.encode(PATH_KEY + "=" + IHelloService.class.getName() + "&" + "mock=fail"));
        Invoker<IHelloService> cluster = getClusterInvoker(url);
        URL mockUrl = URL.valueOf("mock://localhost/" + IHelloService.class.getName() + "?getSomething.mock=return aa");

        Protocol protocol = new MockProtocol();
        Invoker<IHelloService> mInvoker1 = protocol.refer(IHelloService.class, mockUrl);
        invokers.add(mInvoker1);

        // Configured with mock
        RpcInvocation invocation = new RpcInvocation();
        invocation.setMethodName("getSomething");
        Result ret = cluster.invoke(invocation);
        Assertions.assertEquals("something", ret.getValue());

        // If no mock was configured, return null directly
        invocation = new RpcInvocation();
        invocation.setMethodName("sayHello");
        ret = cluster.invoke(invocation);
        Assertions.assertNull(ret.getValue());
    }