private string GenerateVoidMethodExpectationClass(MethodGenerator methodInfo)
        {
            var r = new StringBuilder();

            r.Append($"/// <summary>set the expected behaviour for {methodInfo.Method.Name} Method");
            r.AppendLine("</summary>");
            r.AppendLine($"public class {methodInfo.Method.Name}Expectation");
            r.AppendLine("{");
            r.AppendLine();
            r.AppendLine("internal Nullable<bool> Result;");
            r.AppendLine("internal Exception InvocationFailedException;");
            r.AppendLine($"internal Action<{methodInfo.GetArgsTypes()}> ActionResult;");
            r.AppendLine();
            r.Append("/// <summary>Passes the method execult with no result");
            r.AppendLine("</summary>");
            r.AppendLine("public void Passes()");
            r.AppendLine("{");
            r.AppendLine("Result = true;");
            r.AppendLine("}");
            r.Append("/// <summary>Fails the method execution with an exception");
            r.AppendLine("</summary>");
            r.AppendLine("public void Throws(string message)");
            r.AppendLine("{");
            r.AppendLine("Result = false;");
            r.AppendLine("InvocationFailedException = new Exception(message);");
            r.AppendLine("}");
            r.Append("/// <summary>Fails the method execution with an exception");
            r.AppendLine("</summary>");
            r.AppendLine("public void Throws(Exception ex)");
            r.AppendLine("{");
            r.AppendLine("Result = false;");
            r.AppendLine("InvocationFailedException = ex;");
            r.AppendLine("}");

            r.Append("/// <summary>Executes an expression without returning value");
            r.AppendLine("</summary>");
            r.AppendLine($"public void Does(Action<{methodInfo.GetArgsTypes()}> action)");
            r.AppendLine("{");
            r.AppendLine("Result = null;");
            r.AppendLine("ActionResult = action;");
            r.AppendLine("}");

            r.AppendLine("}");
            return(r.ToString());
        }
        private string GenerateApiBehaviourClass(MethodGenerator methodInfo)
        {
            var r = new StringBuilder();

            r.Append($"/// <summary>Expected behaviour of the mocked {ClassName}.{methodInfo.Method.Name}() method.");
            r.AppendLine("</summary>");
            r.AppendLine($"public partial class {ClassName}Behaviour");
            r.AppendLine("{");
            r.AppendLine($"Dictionary<string,{methodInfo.Method.Name}Expectation> {methodInfo.Method.Name}Expectations");
            r.AppendLine($"= new Dictionary<string,{methodInfo.Method.Name}Expectation>();");
            r.AppendLine();

            // define method without parameters
            r.Append($"/// <summary>Sets the default expected mock result for when {methodInfo.Method.Name}() is called, irrespective of input arguments.");
            r.AppendLine("</summary>");
            r.AppendLine($"public {methodInfo.Method.Name}Expectation {methodInfo.Method.Name}()");
            r.Append(" => ");
            r.AppendLine($"{methodInfo.Method.Name}Expectations[\"\"] = new {methodInfo.Method.Name}Expectation();");
            r.AppendLine();

            var overloads = Context.ActionMethods.Where(x => x.Method.Name == methodInfo.Method.Name).ToList();

            if (overloads.None(x => x.GetArgs().IsEmpty()))
            {
                // All overloads have a value.
                // Define a generic one.
                foreach (var overload in overloads)
                {
                    // define method with parameters
                    r.Append($"/// <summary>Set the mock expectation for {overload.Method.Name} Method");
                    r.AppendLine("</summary>");
                    r.AppendLine($"public {overload.Method.Name}Expectation {overload.Method.Name}({overload.GetArgs()})");
                    r.AppendLine("{");
                    r.AppendLine($"var key=$\"{overload.GetMockKeyExpression()}\";");
                    r.AppendLine($"return {overload.Method.Name}Expectations[key]=new {overload.Method.Name}Expectation();");
                    r.AppendLine("}");
                }
            }
            foreach (var overload in overloads)
            {
                // define result method with parameters
                r.Append($"/// <summary>Get the expected result for {overload.Method.Name}().");
                r.AppendLine("</summary>");
                r.AppendLine($"internal Task{overload.ReturnType.WithWrappers("<", ">")} {overload.Method.Name}Result({overload.GetArgs()})");
                r.AppendLine("{");

                if (methodInfo.HasReturnType())
                {
                    r.AppendLine($"{overload.Method.Name}Expectation expectation;");
                    if (overload.GetArgs().IsEmpty())
                    {
                        r.AppendLine($"if({overload.Method.Name}Expectations.ContainsKey(\"\"))");
                    }
                    else
                    {
                        r.AppendLine($"var key=$\"{overload.GetMockKeyExpression()}\";");
                        r.AppendLine($"if({overload.Method.Name}Expectations.ContainsKey(key))");
                        r.AppendLine($"expectation= {methodInfo.Method.Name}Expectations[key];");
                        r.AppendLine($"else if({overload.Method.Name}Expectations.ContainsKey(\"\"))");
                    }
                    r.AppendLine($"expectation= {methodInfo.Method.Name}Expectations[\"\"];");
                    r.AppendLine("else");
                    r.AppendLine($"throw new Exception(\"Mock expectation is not defined for {overload.Method.Name}().\");");
                    r.AppendLine($"return Task.FromResult(expectation.Result ?? expectation?.FuncResult.Invoke({methodInfo.GetArgsNames()}));");
                }
                else
                {
                    r.AppendLine($"{overload.Method.Name}Expectation expectation;");
                    if (overload.GetArgs().IsEmpty())
                    {
                        r.AppendLine($"if({overload.Method.Name}Expectations.ContainsKey(\"\"))");
                    }
                    else
                    {
                        r.AppendLine($"var key=$\"{overload.GetMockKeyExpression()}\";");
                        r.AppendLine($"if({overload.Method.Name}Expectations.ContainsKey(key))");
                        r.AppendLine($"expectation= {methodInfo.Method.Name}Expectations[key];");
                        r.AppendLine($"else if({overload.Method.Name}Expectations.ContainsKey(\"\"))");
                    }
                    r.AppendLine($"expectation= {methodInfo.Method.Name}Expectations[\"\"];");
                    r.AppendLine("else");
                    r.AppendLine($"throw new Exception(\"Mock expectation is not defined for {overload.Method.Name}().\");");

                    r.AppendLine("if(expectation.Result.HasValue)");
                    r.AppendLine("{");
                    r.AppendLine("if(expectation.Result.Value)");
                    r.AppendLine("return Task.CompletedTask;");
                    r.AppendLine("else");
                    r.AppendLine("throw expectation.InvocationFailedException;");
                    r.AppendLine("}");
                    r.AppendLine("else");
                    r.AppendLine("{");
                    r.AppendLine($"expectation.ActionResult.Invoke({methodInfo.GetArgsNames()});");
                    r.AppendLine("return Task.CompletedTask;");
                    r.AppendLine("}");
                }
                r.AppendLine("}");
                r.AppendLine();
            }
            if (methodInfo.HasReturnType())
            {
                r.AppendLine(GenerateMethodExpectationClass(methodInfo));
            }
            else
            {
                r.AppendLine(GenerateVoidMethodExpectationClass(methodInfo));
            }

            r.AppendLine("}");
            return(r.ToString());
        }
 static bool HasMethodsWithParams(MethodGenerator methodInfo) => Context.ActionMethods.Any(x => x.Method.Name == methodInfo.Method.Name && !x.GetArgs().IsEmpty());
 public static bool HasReturnType(this MethodGenerator @this) => [email protected]();