Example #1
0
        private void MockAllExternalDependencyMethods(Type type, CodeConstructor testClassConstructor,
                                                      AnalyzedSolution analyzedSolution, Type classUnderTestType)
        {
            // - for each discovered/mockable method in type ObjectToBeMocked
            var methods = type.GetMethods(BindingFlags.Public
                                          | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            foreach (MethodInfo m in methods)
            {
                // see if the method should be mocked
                // -- search in the code for all the methods in the CUT to see if the method is invoked somewhere
                // --- if yes, then the method should be mocked
                // --- if no, then that method is not used and it should not be mocked
                bool shouldBeMocked = CheckIfTheMethodShouldBeMocked(type, analyzedSolution, m, classUnderTestType);

                if (shouldBeMocked)
                {
                    // dynamically generate the code for a lamda expression
                    var        parameter  = Expression.Parameter(type, "m");
                    MethodInfo methodInfo = type.GetMethod(m.Name);

                    // randomly generate method parameters
                    var    methodParameters = m.GetParameters();
                    string parameters       = "";
                    int    j = 1;
                    foreach (ParameterInfo p in methodParameters)
                    {
                        var separator = j == methodParameters.Count() ? "" : ", ";
                        parameters += string.Format("It.IsAny<{0}>()", p.ParameterType) + separator;
                        j++;
                    }

                    var lambdaExpr      = string.Format("m => m.{0}({1})", m.Name, parameters);
                    var mockSetupMethod = new CodeMethodInvokeExpression(
                        new CodeVariableReferenceExpression(string.Format("{0}Mock", type.Name)),
                        "Setup", new CodeSnippetExpression(lambdaExpr));

                    // resolve method return type
                    var methodReturnType = m.ReturnType.Name;
                    CodeExpression[] mockReturnMethodParameter = new CodeExpression[1];
                    mockReturnMethodParameter[0] = new CodePrimitiveExpression(
                        _inputParamGenerator.ResolveParameter(methodReturnType));

                    var mockReturnMethod = new CodeMethodInvokeExpression(
                        mockSetupMethod,
                        "Returns", mockReturnMethodParameter);

                    testClassConstructor.Statements.Add(mockReturnMethod);
                }
            }
        }
Example #2
0
        public List <string> GenerateUnitTestsForClass(string solutionPath,
                                                       string generatedUnitTestProject, List <string> projClasses)
        {
            List <string> generatedTestClasses = new List <string>();

            // analyze solution, discover basic information about each project
            var            solutionAnalyzer = new SolutionAnalyzer(solutionPath);
            var            analyedSolution  = solutionAnalyzer.AnalyzeSolution();
            CompilerHelper compileHelper    = new CompilerHelper(_generatedTestClassesDirectory);

            foreach (AnalyzedProject proj in analyedSolution.Projects)
            {
                if (proj.Name != generatedUnitTestProject)
                {
                    var assembly = Assembly.LoadFile(proj.OutputFilePath); //TODO: what if the assembly does not exist because the project is not compiled??
                    _assemblyExportedTypes = assembly.GetExportedTypes();
                    inputParamGenerator    = new InputParamGenerator(_assemblyExportedTypes);

                    foreach (Type type in _assemblyExportedTypes)
                    {
                        if (projClasses.Any(pc => pc == type.Name))
                        {
                            if (!type.IsInterface) // don't want to write unit tests for interfaces
                            {
                                // create a class
                                CodeTypeDeclaration targetClass = new CodeTypeDeclaration
                                                                      (string.Format("{0}UnitTestsClass", type.Name))
                                {
                                    IsClass        = true,
                                    TypeAttributes = TypeAttributes.Public
                                };

                                // create a code unit (the in-memory representation of a class)
                                CodeCompileUnit codeUnit        = CreateCodeCompileUnit(proj.Name, type.Name, targetClass);
                                string          classSourceName = string.Format("{0}UnitTestsClass.cs", type.Name);

                                // generate the constructor for the unit test class in which all the
                                // external dependencies/calls will be mocked
                                var cut_ConstructorGenerator = new CUT_AddConstructor(inputParamGenerator, selectedProjectName);
                                cut_ConstructorGenerator.AddTestClassConstructor(classSourceName, targetClass, type, analyedSolution);

                                // generate a unit test for each method
                                // the method will be called and a Assert.NotNull assertion will be added
                                var methods = type.GetMethods(BindingFlags.Public
                                                              | BindingFlags.Instance | BindingFlags.DeclaredOnly);

                                foreach (MethodInfo m in methods)
                                {
                                    // randomly generate method parameters
                                    var methodParameters        = m.GetParameters();
                                    CodeExpression[] parameters = new CodeExpression[methodParameters.Length];
                                    int j = 0;
                                    foreach (ParameterInfo p in methodParameters)
                                    {
                                        // TODO: Rethink this !!!
                                        if (p.ParameterType.Name == "String" || p.ParameterType.Name == "Int32")
                                        {
                                            parameters[j] = new CodePrimitiveExpression(
                                                inputParamGenerator.ResolveParameter(p.ParameterType.Name));
                                        }
                                        else
                                        {
                                            CodeObjectCreateExpression createObjectExpression =
                                                inputParamGenerator.CreateCustomType(p.ParameterType.Name);
                                            parameters[j] = createObjectExpression;
                                        }
                                        j++;
                                    }

                                    var cut_addTestMethod = new CUT_AddTestMethod(inputParamGenerator);

                                    // Assert.NotNull(result);
                                    // Assert.NotThrow(() => targetObj.SomePublicMethod())
                                    cut_addTestMethod.AddTestMethod_ShouldNotThrowExceptionResultShouldNotBeNull(targetClass, m.Name,
                                                                                                                 parameters, type, "CallShouldNotThrowExceptionAndResultShouldNotBeNull");

                                    // Assert.AreEqual(result, "Insert expected value here.");
                                    cut_addTestMethod.AddTestMethod_ExpectedResultPlaceholder(targetClass, m.Name,
                                                                                              parameters, type, "ResultShouldBeAsExpected");
                                }

                                // generate the c# code based on the created code unit
                                string generatedTestClassPath = compileHelper.GenerateCSharpCode(codeUnit, classSourceName);

                                // compile the above generated code into a DLL/EXE
                                bool isGeneratedClassCompiled = compileHelper.CompileAsDLL(classSourceName, new List <string>()
                                {
                                    string.Format("{0}\\{1}", _packagesFolder, "NUnit.3.10.1\\lib\\net45\\nunit.framework.dll"),
                                    string.Format("{0}\\{1}", _packagesFolder, "Moq.4.10.0\\lib\\net45\\Moq.dll"),
                                    proj.OutputFilePath,
                                    typeof(System.Linq.Enumerable).Assembly.Location
                                });

                                if (!string.IsNullOrEmpty(generatedTestClassPath) && isGeneratedClassCompiled)
                                {
                                    generatedTestClasses.Add(generatedTestClassPath);
                                }
                            }
                        }
                    }
                }
            }

            return(generatedTestClasses);
        }