开发者

What approach to take for testing AutoMapper configuration in an ASP.NET MVC application?

We are using AutoMapper extensively in our ASP.NET MVC web applications with the AutoMapViewResult approach set out in this question. So we have actions that look like this:

public ActionResult Edit(User item)
{
    return AutoMapView<UserEditModel>(View(item));
}

This creates hidden failure points in the application if the requested mapping has not been configured - in that this is not a compile time fail.

I'm looking at putting something in place to test these mappings. As this needs to test the actual AutoMapper configuration I presume this should be done as part of integration testing? Should these tests be structured per controller or per entity? What about the possibility of automatically parsing all calls to AutoMapView?

Note that we are already testing that the AutoMapper configuration is valid using As开发者_运维技巧sertConfigurationIsValid, it is missing mappings that I want to deal with.


If your controller action looked like this:

public AutoMapView<UserEditModel> Edit(User item)
{
    return AutoMapView<UserEditModel>(View(item));
}

Then you can pretty easily, using reflection, look for all controller actions in your project. You then examine the action parameter types and the generic type parameter of your AutoMapView action result. Finally, you ask AutoMapper if it has a type map for those input/output models. AutoMapper doesn't have a "CanMap" method, but you can use the IConfigurationProvider methods of FindTypeMapFor:

((IConfigurationProvider) Mapper.Configuration).FindTypeMapFor(null, typeof(User), typeof(UserEditModel);

Just make sure that's not null.


    [Test]
    public void MapperConfiguration()
    {
        var mapper = Web.Dto.Mapper.Instance;
        AutoMapper.Mapper.AssertConfigurationIsValid();
    }


You can use the AssertConfigurationIsValid method. Details are on the automapper codeplex site (http://automapper.codeplex.com/wikipage?title=Configuration%20Validation)

Strictly speaking you should be writing a test to validate the mapping before you write a controller action that depends on the mapping configuration being present.

Either way, you can use the Test Helpers in the MvcContrib project to check the action method returns the expected ViewResult and Model.

Here's an example:

            pageController.Page("test-page")
            .AssertViewRendered()
                .WithViewData<PortfolioViewData>()
                    .Page
                        .ShouldNotBeNull()
                        .Title.ShouldEqual("Test Page");


I do something like this.

using System.Linq;
using System.Reflection;
using AutoMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;

public class SampleDto
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Sample
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string LoginId { get; set; }
}

public class AutomapperConfig
{
    public static void Configure()
    {
        Mapper.Initialize(cfg => cfg.AddProfile<ViewModelProfile>());
    }
}

public class ViewModelProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<SampleDto, Sample>();
    }
}

[TestClass]
public class AutoMapperTestsSample
{
    public AutoMapperTestsSample()
    {
        AutomapperConfig.Configure();
    }


    [TestMethod]
    public void TestSampleDtoFirstName()
    {
        #region Arrange
        var source = new SampleDto();
        source.FirstName = "Jim";
        //source.LastName = "Bob";
        var dest = new Sample();
        dest.FirstName = "FirstName";
        dest.LastName = "LastName";
        dest.LoginId = "LoginId";
        #endregion Arrange

        #region Act
        AutoMapper.Mapper.Map(source, dest);
        #endregion Act

        #region Assert
        Assert.AreEqual("Jim", dest.FirstName);
        Assert.AreEqual(null, dest.LastName);
        Assert.AreEqual("LoginId", dest.LoginId);
        #endregion Assert       
    }

    [TestMethod]
    public void TestSampleDtoLastName()
    {
        #region Arrange
        var source = new SampleDto();
        //source.FirstName = "Jim";
        source.LastName = "Bob";
        var dest = new Sample();
        dest.FirstName = "FirstName";
        dest.LastName = "LastName";
        dest.LoginId = "LoginId";
        #endregion Arrange

        #region Act
        AutoMapper.Mapper.Map(source, dest);
        #endregion Act

        #region Assert
        Assert.AreEqual(null, dest.FirstName);
        Assert.AreEqual("Bob", dest.LastName);
        Assert.AreEqual("LoginId", dest.LoginId);
        #endregion Assert
    }

    /// <summary>
    /// This lets me know if something changed in the Dto object so I know to adjust my tests
    /// </summary>
    [TestMethod]
    public void TestSampleDtoReflection()
    {
        #region Arrange
        var xxx = typeof(SampleDto);
        #endregion Arrange

        #region Act
        #endregion Act

        #region Assert
        Assert.AreEqual(2, xxx.GetRuntimeFields().Count());
        Assert.AreEqual("System.String", xxx.GetRuntimeFields().Single(a => a.Name.Contains("FirstName")).FieldType.ToString());
        Assert.AreEqual("System.String", xxx.GetRuntimeFields().Single(a => a.Name.Contains("LastName")).FieldType.ToString());            
        #endregion Assert       
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜