Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoMapper testing and dependency injection for resolvers

Im writing a test for an automapper map. One of the destination members in the map requires a value resolver, and that value resolver has service dependencies which are injected. I want to use the real implementation for the resolver (since thats part of the map im testing) but Id like to use mocks for the dependencies the resolver has.

Ofcourse I want to try to avoid using an ioc container for in my tests, but how do I easily resolve my value resolver's dependencies without one?

This is my rather simplified example, in the real case there are several resolvers with sometimes many dependencies, and I really dont like to basically implement my own dependency resolver in my tests. Should I use a lightweight ioc container?

        [TestFixture]
        public class MapperTest
        {
            private IMyService myService;

            [SetUp]
            public void Setup()
            {
                Mapper.Initialize(config =>
                                    {
                                    config.ConstructServicesUsing(Resolve);
                                    config.AddProfile<MyProfile>();
                                    });
            }

            public T Resolve<T>()
            {
                return (T) Resolve(typeof (T));
            }

            public object Resolve(Type type)
            {
                if (type == typeof(MyValueResolver))
                    return new MyValueResolver(Resolve<IMyService>());
                if (type == typeof(IMyService))
                    return myService;
                Assert.Fail("Can not resolve type " + type.AssemblyQualifiedName);
                return null;
            }

            [Test]
            public void ShouldConfigureCorrectly()
            {
                Mapper.AssertConfigurationIsValid();
            }

            [Test]
            public void ShouldMapStuff()
            {
                var source = new Source() {...};
                var child = new Child();
                myService = MockRepository.GenerateMock<IMyService>();

                myService .Stub(x => x.DoServiceStuff(source)).Return(child);

                var result = Mapper.Map<ISource, Destination>(source);

                result.Should().Not.Be.Null();
                result.Child.Should().Be.SameInstanceAs(child);
            }

        }


        public class MyProfile : Profile
        {

            protected override void Configure()
            {
                base.Configure();

                CreateMap<ISource, Destination>()
                    .ForMember(m => m.Child, c => c.ResolveUsing<MyResolver>());

            }

       }

       public class MyResolver: ValueResolver<ISource, Destination>
        {
            private readonly IMyService _myService;

            public MyResolver(IMyService myService)
            {
                _myService = myService;
            }

            protected override Child ResolveCore(ISource source)
            {
                             return _myService.DoServiceStuff(source);
            }
        }
    }
like image 419
MatteS Avatar asked May 27 '11 08:05

MatteS


People also ask

How do I test AutoMapper configuration?

To test our configuration, we simply create a unit test that sets up the configuration and executes the AssertConfigurationIsValid method: var configuration = new MapperConfiguration(cfg => cfg. CreateMap<Source, Destination>()); configuration. AssertConfigurationIsValid();

How do I use ForMember in AutoMapper?

CreateMap<EFAddress, Address>() . ForMember(dest => dest. Code, opt => opt. MapFrom(src => src.Name));

Is AutoMapper a singleton?

Your configuration (e.g. Automapper Profiles) are singletons. That is, they are only ever loaded once when your project runs. This makes sense since your configurations will not change while the application is running. The IMapper interface itself is “scoped”.


1 Answers

Here's one solution, but basically its what iv done already:

http://groups.google.com/group/automapper-users/browse_thread/thread/aea8bbe32b1f590a/f3185d30322d8109

The suggestion is to use a service locator which are set up differently depending on test or real implementation.

like image 124
MatteS Avatar answered Oct 17 '22 13:10

MatteS