How should I use AutoMapper?

by Mikael Henriksson 13. February 2010 16:12

It is actually really simple and I have to thank my boss, DBA and friend Fridthjof for that. If you ever thought it is difficult to work with a DBA then imagine having one as your boss! *joke*  

He’s a great guy and as a DBA he is actually very understanding and I have been able to use pretty much any tool I want to get the job done as long as I don’t use CamelCase names in the database. Since we are using whatever tools we feel might get us there the quickest/easiest we have gone down different paths where I have spent a bit more time setting things up with NHibernate whereas my colleague has chosen to move quicker initially with LINQ to SQL  and use Fridthjof to do the queries in form of stored procedures for him. It’s worked out great for both of us though for me it took a while longer but yesterday when we where going to synchronize  our works I found that in the other projects he ran in to having to do all the work two times or so because of the different naming standards in the database and C#. I instantly came to think of AutoMapper so I suggested it, helped him set it up for what I needed from him (took a couple of minutes until it was deployed) and I am pretty sure that I will have his eternal gratitude for showing him AutoMapper. Question is how do I setup AutoMapper? Example below:

 

[Test]
public void AutoMapper_configuration_should_be_valid()
{
	Mapper.CreateMap<ContactQuery, ContactInfo>()
		.ForMember(dest => dest.SomeProperty, opt => opt.Ignore());

	Mapper.CreateMap<ContactInfo, ContactQuery>()
		.ForMember(dest => dest.FirstVersionAt, opt => opt.Ignore())
		.ForMember(dest => dest.LastVersionAt, opt => opt.Ignore())
		.ForMember(dest => dest.MaxResult, opt => opt.Ignore());
	
	Mapper.AssertConfigurationIsValid();
}

 

You can of course do much more than this with AutoMapper but it’s a good start the above is a test verifying that the maps I just setup is valid. don’t worry. AutoMapper will tell you exactly what your mapping problems are. This type of mapping should of course not be confused with NHibernate mappings but they are basically the same thing between two objects instead of between one object and one table.

So how do I use this map then?

var contact = new ContactInfo { ContactId = 1 };
var query = Mapper.Map<ContactInfo, ContactQuery>(contact);

So far so good BUT! This is doing the same thing / writing the same code in two places and you should really not repeat yourself. Time to DRY up and place that in a Profile of the project using it. (I know the documentation is blank =:])  That way it’s really easy to add a test for it and reset the test afterwards so that we at least keep the Assertions to just validating the bare minimum.

public class ContactProfile : Profile
{
	protected override void Configure()
	{
		CreateMap<ContactInfo, ContactQuery>()
			.ForMember(dest => dest.FirstVersionAt, opt => opt.Ignore())
			.ForMember(dest => dest.LastVersionAt, opt => opt.Ignore())
			.ForMember(dest => dest.MaxResult, opt => opt.Ignore());

		CreateMap<ContactQuery, ContactInfo>()
			.ForMember(dest => dest.SomeProperty, opt => opt.Ignore());
	}

	protected override string ProfileName
	{
		get { return "Sync"; }
	}
}

Now then a test to prove that my mappings are actually valid. I like to clear everything both before the test and after the test to be sure I only validate the necessary mappings:

[TestFixture]
public class Verify_AutoMapper_mappings_for
{
	[Test]
	public void ContactProfile()
	{
		Mapper.Reset();
		Mapper.AddProfile<ContactProfile>();
		Mapper.AssertConfigurationIsValid();
		Mapper.Reset();
	}
}

Tags: , ,

C# | Testing | AutoMapper

Unit testing private methods

by Mikael Henriksson 8. January 2010 12:54

Sometimes I can’t be bothered about testing the whole shebang. I just want to test what really counts without having to go through mocking external calls just to verify that something returns true.

This is probably not how one should test code but what the helicopter it works.

[Test]
public void Testing_a_private_method()
{
    BindingFlags Flags = BindingFlags.NonPublic | BindingFlags.Instance;
    var instance = new SomeInstance();
    Type type = typeof(SomeInstance);
    var para = new SomeParameterClass()
    para.SomeProperty1 = 2;
    para.SomeProperty2 = 1;
    var parameters = new object[] { para };

    MethodInfo method = type.GetMethod("InstanceMethodName", Flags);
    object obj = method.Invoke(instance, parameters);
    Assert.AreEqual(true, Convert.ToBoolean(obj));
}

EDIT: Inspired by Jan Van Ryswyck I decided to add a much cleaner way of doing this using Func<TInput, TOutput>. I recommend you read his post.

[Test]
public void Testing_a_private_method()
{
    var instance = new SomeInstance();
    var para = new SomeParameterClass()
    para.SomeProperty1 = 2;
    para.SomeProperty2 = 1;
    
    var instanceMethodName = (Func< SomeParameterClass, bool>)
    Delegate.CreateDelegate(
		typeof(Func< SomeParameterClass, bool>), instance, "InstanceMethodName"
		);
    Assert.IsTrue(instanceMethodName(para), "This should really return true");
}

Like Jan mentions it does only work for instance methods not static ones but you shouldn’t be creating too many static methods anyway :)

EDIT2: Also worth noting is that Func of course only works for methods that actually return something. If you need to check the values of something that should have been manipulated without the method returning the manipulated value we need to use another Delegate, say hello to Action!

[Test]
public void Testing_a_private_method()
{
    var instance = new SomeInstance();
    var para = new SomeParameterClass()
    para.SomeProperty1 = 2;
    para.SomeProperty2 = 1;
    
    var instanceMethodName = (Action< SomeParameterClass, bool>)
    Delegate.CreateDelegate(
		typeof(Action< SomeParameterClass, bool>), instance, "InstanceMethodName"
		);
    instanceMethodName(para);
    Assert.AreEqual(2, para.SomeProperty2, "Since we set SomeProperty2 to initial value 1 this will throw if it's not been set while InstanceMethodName executed!");
}

Tags:

Testing

How to waste half a day getting R# to run unit tests…

by Mikael Henriksson 10. December 2009 14:11

Today I feel like the most retarded guy on planet earth. I have just wasted half a day trying to get R# to run my unit tests. The tests simply does not even start so they don’t fail either. 
A check of the output window shows that there is a possible chance of a FileNotFoundException which I thought was bullshit. I had a look at the settings for R# Unit Test and no there was nothing that I could do to make it work. Since I AM a smart guy usually (I am just feeling a bit stupid today) I decided to make all exceptions throw so that I could at least find some sort of trace or hint of where the problem actually occurs.

Ctrl+Alt+E takes you to the Visual Studio exceptions settings where I turn everything to throw and then I start debugging the unit tests. After a good few clicks some interesting exceptions shows up. It’s a FileNotFoundException and it looks like this:

System.IO.FileNotFoundException occurred
  Message="Could not load file or assembly 'file:///D:\\Apps\\NUnit 2.5.2\\bin\\net-2.0\\lib\\nunit.core.dll' or one of its dependencies. The system cannot find the file specified."
  Source="mscorlib"
  FileName="file:///D:\\Apps\\NUnit 2.5.2\\bin\\net-2.0\\lib\\nunit.core.dll"
  FusionLog="=== Pre-bind state information ===
  LOG: User = MOBILENORDIC\\mikael
  LOG: Where-ref bind. Location = D:\\Apps\\NUnit 2.5.2\\bin\\net-2.0\\lib\\nunit.core.dll
  LOG: Appbase = file:///D:/Projects/****.IntegrationTests/bin/Debug
  LOG: Initial PrivatePath = NULL
  Calling assembly : (Unknown).===
  LOG: This bind starts in LoadFrom load context.
  WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
  LOG: Using application configuration file: D:/Projects/****.IntegrationTests\\bin\\Debug\\*.IntegrationTests.dll.config
  LOG: Using machine configuration file from C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\config\\machine.config.
  LOG: Attempting download of new URL file:///D:/Apps/NUnit 2.5.2/bin/net-2.0/lib/nunit.core.dll."
  StackTrace:
       at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
       at System.Reflection.Assembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, StackCrawlMark& stackMark)
       at System.Reflection.Assembly.LoadFrom(String assemblyFile)
       at JetBrains.ReSharper.UnitTestProvider.nUnit.NUnitTaskRunner.ExecuteRecursive(TaskExecutionNode node) in c:\Agent\work\cc29ccea5bf569df\src\UnitTestProvider.nUnit\src\NUnitTaskRunner.cs:line 103
  InnerException: 

Well interesting, it turned out that it was actually me being stupid. I was positive this had nothing to do with R# but the level of retardness does not stop here! I go back to the R# settings and look for somewhere to change the path to nunit but can’t find anything so I rename my d:\apps\nunit folder to match the one I couldn’t find and try again and now my unit tests run perfectly. I decided the bloody thing had messed with me for the last time! Going back to the settings for Unit Tests in R# I am faced with the following picture:

resharper_unit_test_settings

Now where the heck is that darn setting??? I open up the resharper.user file in notepad2 and search for nunit and at the bottom I found this:

  <UnitTestRunnerNUnit>
    <NUnitInstallDir>D:\Apps\NUnit 2.5.2\bin\net-2.0</NUnitInstallDir>
    <UseAddins>Always</UseAddins>
    <UseSpecifiedNUnit>True</UseSpecifiedNUnit>
  </UnitTestRunnerNUnit>

Now I can change this to the folder where it is REALLY located and that is great when it hits me. I remember changing this in resharper for some stupid reason and I also remember that I did so within the Resharper Unit Test section of the options. While navigating back and clicking on nunit I am looking at the following picture:

resharper_nunit_settings

 

Either I am mentally retarded or that part of the ReSharper options is so pick your choice.

Tags: ,

FAIL | R# | Testing

UnitTesting with SQLite

by Mikael Henriksson 25. October 2009 00:34

I just had one of those frustrating moments where the unit tests on my machine works but those on the build server does not! This time I was pretty sure what the issue was. Any time that StructureMap tries to build the session factory and this fails I get strange exceptions in places that hasn’t even been hit. This caused me to first ponder why it would not configure NHibernate on the build server and instantly I thought of SQLite. Now don’t get me wrong I love SQLite but the difference between the x64 and the x86 version has caused me a lot of problems.

I ended up checking if the build number property is set in the build script and if so copy the x86 version of System.Data.SQLite.dll and overwrite the x64 one I use by default. I wouldn’t say that is convention over configuration… I’d say it’s a kick in the nuts for convention this time but it’ll have to do.

Tags: , , ,

NAnt | Team City | Testing | NUnit

Testing…

by Mikael Henriksson 19. September 2009 13:37

I find myself drifting more and more towards something I believe is TDD. When I start with something new I go to my test project, write a test (spec) of what I want to accomplish and then try to produce code that tries to satisfy the spec (test).

I don’t care that much about what others say about patterns or whatever I just care about that things should work. It’s not like I can blame anyone except myself if I cause a stop in production. There for I like to follow some steps when I do testing.

  1. Simple unit tests
  2. Data verification tests
  3. Integration tests simulating a client
  4. Using a real client

If I get success on all these I don’t mind saying ooops if something goes wrong. Without knowing that my functions do what they are supposed to, that the data sanity is in check and that both simulation and real clients work as they should I don’t like to release things. Fortunately this is not very hard to achieve and even badly written, hard to use tests are much better than not testing at all and practice makes perfect :)

Tags:

Testing

About the author

Life architect specialized in programming