Ejemplo n.º 1
0
        /// <summary>
        /// Prepares the mocks, dependencies and the item under test.
        /// </summary>
        /// <exception cref="LeapingGorilla.Testing.Exceptions.NoItemUnderTestException">Thrown if the user has specified [Dependency]'s but there is no [ItemUnderTest]</exception>
        /// <exception cref="NoMatchingConstructorFoundException">Thrown if no constructor can be found on the [ItemUnderTest] that matches the number of [Dependency] fields/properties</exception>
        /// <exception cref="DependencyMismatchException">Thrown if a [Dependency] cannot be found for a constructor parameter when one is expected.</exception>
        /// <exception cref="NoItemUnderTestException">Thrown if there are fields/properties marked with [Dependency] but none with [ItemUnderTest]</exception>
        private void PrepareMocksDependenciesAndItemUnderTest()
        {
            // Create a fast accessor onto the test class
            var accessor = TypeAccessor.Create(GetType(), true);

            // Get and validate the item under test
            var itemUnderTest = GetPropertiesWithAttribute(typeof(ItemUnderTestAttribute)).Select(pi => new { Type = pi.PropertyType, pi.Name })
                                .Concat(GetFieldsWithAttribute(typeof(ItemUnderTestAttribute)).Select(pi => new { Type = pi.FieldType, pi.Name }))
                                .FirstOrDefault();

            // Create mocks and dependencies
            CreateManualDependencies();
            var dependencies = CreateAndAssignPropertiesOrFieldsWithAttribute(accessor, typeof(DependencyAttribute));

            dependencies.AddRange(CreateAndAssignPropertiesOrFieldsWithAttribute(accessor, typeof(NullDependencyAttribute)));

            CreateAndAssignPropertiesOrFieldsWithAttribute(accessor, typeof(MockAttribute));

            // It is invalid to have dependencies but no item under test
            if (itemUnderTest == null)
            {
                if (dependencies.Count > 0)
                {
                    throw new NoItemUnderTestException();
                }

                // No item under test but no dependencies. We can abort out of the rest of the setup
                return;
            }

            // Determine the correct constructor for the item under test. If we cant match one then error out
            var constructor = GetPreferredConstructor(itemUnderTest.Type, dependencies);

            if (constructor == null)
            {
                throw new NoMatchingConstructorFoundException(dependencies);
            }


            var parameters           = constructor.GetParameters();
            var constructorArguments = new object[parameters.Length];

            // Assign parameters. We remove them from the dependencies list as we go so we don't re-use dependencies in case of indirect (type only) matching
            for (int index = 0; index < parameters.Length; index++)
            {
                var param = parameters[index];
                var dep   = dependencies.FirstOrDefault(d => d.Name == param.Name && d.Type == param.ParameterType) ?? dependencies.FirstOrDefault(d => d.Type == param.ParameterType);

                if (dep == null)
                {
                    throw new DependencyMismatchException(param.ParameterType, param.Name, index, parameters);
                }

                dependencies.Remove(dep);
                constructorArguments[index] = dep.Value;
            }

            // Create the item under test and load it into the test class
            accessor[this, itemUnderTest.Name] = Activator.CreateInstance(itemUnderTest.Type, constructorArguments);
        }
Ejemplo n.º 2
0
        private List <Dependency> CreateAndAssignPropertiesOrFieldsWithAttribute(TypeAccessor accessor, Type attributeType)
        {
            var dependencies = BuildDependenciesForPropertiesOrFieldsWithAttributeType(attributeType);

            foreach (var dep in dependencies)
            {
                accessor[this, dep.Name] = dep.Value;
            }

            return(dependencies);
        }