Obviously, you have to test mapping code somehow, even (or especially) if you use AutoMapper. Is there any way to make it less verbose?
[Test]
public void Map_Always_SetsSimpleProperties()
{
var auctionPlace = fixture.Create<string>();
var submissionCloseDateTime = fixture.Create<DateTime>();
var quotationForm = fixture.Create<string>();
var quotationExaminationDateTime = fixture.Create<DateTime>();
var envelopeOpeningTime = fixture.Create<DateTime>();
var envelopeOpeningPlace = fixture.Create<string>();
var auctionDateTime = fixture.Create<DateTime>();
var applExamPeriodDateTime = fixture.Create<DateTime>();
var considerationSecondPartDate = fixture.Create<DateTime>();
var doc = fixture.Create<Notification223>();
doc.AuctionPlace = auctionPlace;
doc.SubmissionCloseDateTime = submissionCloseDateTime;
doc.QuotationForm = quotationForm;
doc.QuotationExaminationTime = quotationExaminationDateTime;
doc.EnvelopeOpeningTime = envelopeOpeningTime;
doc.EnvelopeOpeningPlace = envelopeOpeningPlace;
doc.AuctionTime = auctionDateTime;
doc.ApplExamPeriodTime = applExamPeriodDateTime;
doc.ConsiderationSecondPartDate = considerationSecondPartDate;
var sut = CreateSut();
var actual = sut.Map(doc);
Assert.That(actual.AuctionPlace, Is.EqualTo(auctionPlace));
Assert.That(actual.SubmissionCloseDateTime, Is.EqualTo(submissionCloseDateTime));
Assert.That(actual.QuotationForm, Is.EqualTo(quotationForm));
Assert.That(actual.QuotationExaminationDateTime, Is.EqualTo(quotationExaminationDateTime));
Assert.That(actual.EnvelopeOpeningTime, Is.EqualTo(envelopeOpeningTime));
Assert.That(actual.EnvelopeOpeningPlace, Is.EqualTo(envelopeOpeningPlace));
Assert.That(actual.AuctionDateTime, Is.EqualTo(auctionDateTime));
Assert.That(actual.ApplExamPeriodDateTime, Is.EqualTo(applExamPeriodDateTime));
Assert.That(actual.ConsiderationSecondPartDate, Is.EqualTo(considerationSecondPartDate));
}
2 Answers 2
Unfortunately, I don't think so.
There is a question about this topic on the website of Dozer (which is a similar library for Java) which mentions a trick:
Should I write unit tests for data mapping logic that I use Dozer to perform?
[...]
Regardless of whether or not you use Dozer, unit testing data mapping logic is tedious and a necessary evil, but there is a trick that may help. If you have an assembler that supports mapping 2 objects bi-directionally, in your unit test you can do something similar to the following example. This also assumes you have done a good job of implementing the
equals()
method for your data objects. The idea is that if you map a source object to a destination object and then back again, the original src object should equal the object returned from the last mapping if fields were mapped correctly. [...]
I think this trick won't find bugs when, for example, doc.ApplExamPeriodTime
is mapped to actual.ConsiderationSecondPartDate
and
doc.ConsiderationSecondPartDate
is mapped to actual.ApplExamPeriodTime
. I don't know that these kind of bugs are possible with AutoMapper or not.
Furthermore, if you need only one directional mapping, I think the most simple solution is the one that's already in your question, I'd go with that. Adding code for the reverse mapping to the production code would be a test smell (Test Logic in Production).
-
\$\begingroup\$ Well, what if I actually need only one direction? I strongly dislike the idea of putting something in a public API just for sake of testing. \$\endgroup\$vorou– vorou2014年01月30日 03:36:55 +00:00Commented Jan 30, 2014 at 3:36
-
\$\begingroup\$ @vorou: I think in that case the only solution is that that you showed in your question. What method do you think of as putting it public for only testing? \$\endgroup\$palacsint– palacsint2014年01月30日 21:15:14 +00:00Commented Jan 30, 2014 at 21:15
-
\$\begingroup\$ I'm talking about reverse mapping, I don't have such method right now. \$\endgroup\$vorou– vorou2014年01月31日 09:22:59 +00:00Commented Jan 31, 2014 at 9:22
-
\$\begingroup\$ @vorou: I've update the answer a little bit. \$\endgroup\$palacsint– palacsint2014年02月01日 10:20:14 +00:00Commented Feb 1, 2014 at 10:20
Yes, you can make it less verbose.
I assume you are using AutoFixture in you call to Create()?
If so, this will create random values out of the box. No need to specify the content and assign each property. Create the source object for mapping, map it, compare the mapped values with the properties on the source object:
[Test]
public void Map_Always_SetsSimpleProperties()
{
var doc = fixture.Create<Notification223>(); // Autofixture will fill properties with random data.
var sut = CreateSut();
var actual = sut.Map(doc);
Assert.That(actual.AuctionPlace, Is.EqualTo(doc.AuctionPlace));
Assert.That(actual.SubmissionCloseDateTime, Is.EqualTo(doc.SubmissionCloseDateTime));
Assert.That(actual.QuotationForm, Is.EqualTo(doc.QuotationForm));
Assert.That(actual.QuotationExaminationDateTime, Is.EqualTo(doc.QuotationExaminationDateTime));
Assert.That(actual.EnvelopeOpeningTime, Is.EqualTo(doc.EnvelopeOpeningTime));
Assert.That(actual.EnvelopeOpeningPlace, Is.EqualTo(doc.EnvelopeOpeningPlace));
Assert.That(actual.AuctionDateTime, Is.EqualTo(doc.AuctionDateTime));
Assert.That(actual.ApplExamPeriodDateTime, Is.EqualTo(doc.ApplExamPeriodDateTime));
Assert.That(actual.ConsiderationSecondPartDate, Is.EqualTo(doc.ConsiderationSecondPartDate));
}
-
\$\begingroup\$ Note that OmitAutoProperties will disable this functionality. It is on by default. \$\endgroup\$PMBjornerud– PMBjornerud2016年02月17日 09:49:03 +00:00Commented Feb 17, 2016 at 9:49
fixture.Create
? \$\endgroup\$