Archives

  • Categories

  • Using RhinoAutoMocker with Property Injection.

    I am a big fan of using StructureMap’s Automocker when unit testing as it stops me writing a lot of repetitive code.

    If you haven’t used it before go and have a look, all you need to do is download StructureMap from here and reference the StructureMap.AutoMocking.dll.

    What does an AutoMocking container do? Well consider the following class.

            public ExampleClass(IDependency1 dependency1, IDependency2 dependency2)
            {
                _dependency1 = dependency1;
                _dependency2 = dependency2;
            }
    

    If we wanted to test this class we would most probably use our Mocking framework to create mocks for our dependencies and inject them into the class. This is fine buts its repetitive coding. When you use an Automocking container it looks at the constructor for you and creates the mocks for you saving you all that effort.

    Derik Whittaker has a much better post on why you should use an AutoMocker here..

    Anyway there is one thing that RhinoAutoMocker doesn’t do and is allow you inject your dependencies into a class using property injection. Now 99% of the time I would recommend using constructor injection however there are times when your IOC container won’t know the whole dependency chain at the time of your object creation and must inject it at a later stage..Anyway that sounds like the topic for another post.

    So if you want to use RhinoAutoMocker and still be able to set any dependencies using property injection here is an extension method that will allow you to do this.

      public static void RegisterPropertyDependency<TARGETCLASS, TProperty>(
                this RhinoAutoMocker<TARGETCLASS> autoMocker, Expression<Func<TARGETCLASS, TProperty>> expression)
                where TARGETCLASS : class
            {
                var body = expression.Body as MemberExpression;
    
                if (body != null)
                {
                    // Work out the type from our expression tree.
                    var propertyInfo = (PropertyInfo) body.Member;
                    var propertyType = propertyInfo.PropertyType;
    
                    // We know the property type now so
                    // we can create a Stub of it using Rhino Mocks.
                    var mockDependency = MockRepository
                                       .GenerateStub(propertyType, null);
    
                    // inject in our stub.
                    autoMocker.Inject(propertyType, mockDependency);
    
                    var propertyName = propertyInfo.Name;
    
                    var classUnderTestType = autoMocker.ClassUnderTest.GetType();
    
                    var dependencyPropertySetMethod = classUnderTestType.GetProperty(propertyName).GetSetMethod();
    
                    dependencyPropertySetMethod
                .Invoke(autoMocker.ClassUnderTest, new[] {mockDependency});
                }
            }
    

    Now consider our example class again with its second dependency being injected through a property.

        class ExampleClass
        {
            private readonly IDependency1 _dependency1;
    
            public ExampleClass(IDependency1 dependency1)
            {
                _dependency1 = dependency1;
            }
    
            public IDependency2 Dependency2 { get; private set; }
        }
    

    To test test this class we need to tell the AutoMocker that the property is to be used for property injection like so.

    
            var autoMocker = new RhinoAutoMocker<ExampleClass>();
    
            automocker.RegisterPropertyDependency(classUnderTest =>  classUnderTest.Dependency2);
    

    Now we can access the mock object to set its behavior through the Auto mocker as we would any other dependency created by the Auto mocker.

    
            var autoMocker = new RhinoAutoMocker<ExampleClass>();
    
            automocker.Get<IDependency2>()
                            .Stub(x =>  x.SomeMethod())
                            .Return(true);
    

    Leave a Reply