VS2012, EF, and Mocking

A couple of years ago I presented at TriNug’s code camp a way to build an interface for EF 1.0 using partial classes.  I thought I would revisit that with VS2012 to see if it is still possible using EF 5.0 and the mocking framework in VS2012.

My first stop was to  install SQL Server Express and then Run Northwind.exe.  Note that you can’t just attach to the Northwind .mdf because of version incompatibilities.  Rather, you need to open SQL Server Express and run the scripts that came with the install.  In any event, once it is installed, it was straight forward to add an EF representation to the project.  The one cool thing that I noticed is that you can change the color of different tables via the property panel:

image

Sure enough, by changing the fill color, you get a really cool effect like this:

image

With EF added to the project, coded up a factory like this:

public List<Territory> GetTerritoriesForARegionId(Int32 regionId)
{
    List<Territory> territories = null;

    if (regionId < 0)
    {
        throw new ArgumentOutOfRangeException("regionId cannot be less than 0");
    }

    using (NorthwindEntities entities = new NorthwindEntities())
    {
        territories = entities.Territories.Where(t => t.RegionID == regionId).ToList();
    }

    return territories;
}

I then went to right click –> add Tests like you do in VS2010 and… Oh No!  That feature is not in VS2012

I then went to hand-code a unit test project, class, and method like this:

[TestMethod]
public void GetTerritoryForARegionIdWithRegionIdOne_ReturnsThreeRecords()
{
    TerritoryFactory factory = new TerritoryFactory();
    List<Territory> territories = factory.GetTerritoriesForARegionId(1);

    Int32 expected = 3;
    Int32 actual = territories.Count;

    Assert.AreEqual(expected, actual);
}

When I ran it, I got this:

image

I needed to copy/paste the .config over.  (Which is the 1st clue that my test is is actually an integration test).  I then ran the test and got red:

image

So there are 19 records in the database.  I can do a couple of things here.  I could check that any value is coming out of the database:

[TestMethod]
public void GetTerritoryForARegionIdWithRegionIdOne_ReturnsThreeRecords()
{
    TerritoryFactory factory = new TerritoryFactory();
    List<Territory> territories = factory.GetTerritoriesForARegionId(1);
    Assert.IsNotNull(territories);

}

The problem is that the working code will always return a instance – unless an exception is thrown. I suppose I can leave the list as null and put a try…catch around the lambda, but that doesn’t really get you anything.  So really, what do you need to test? It is the lambda expression in the working code:

territories = entities.Territories.Where(t => t.RegionID == regionId).ToList();

The problem is that the working code (and therefore the test) is dependent on the entity framework. Breaking the expression into 2 parts, I don’t need to test if the EF does its job, I only need to test my code:

t => t.RegionID == regionId

So how to I make sure you are writing the correct statement to pull down the results you expect? I need to isolate the statement and following functional programming, guarantee that the result will be the same.

To that end, I need to remove the dependency on volatile data. So no database. So how do you make a EF that is not database specific? You sub it out. There are a couple of options (xUnit Test Patterns p.171) . The way I favor is to first inject that context into any class that is using it (and I prefer property injection over constructor injection). 

Note that the dependent class no longer controls the lifetime of the context, so no “using” statement in it.

public class TerritoryFactory
{
    public NorthwindEntities NorthwindEntities { get; set; }

    public List<Territory> GetTerritoriesForARegionId(Int32 regionId)
    {
        List<Territory> territories = null;

        if (regionId < 0)
        {
            throw new ArgumentOutOfRangeException("regionId cannot be less than 0");
        }

        territories = this.NorthwindEntities.Territories.Where(t => t.RegionID == regionId).ToList();

        return territories;
    }
}

Once I am injecting the context, I can pass in a local instance of an EF Context. A If I want to sub out a different version, you need to implement an interface.

The problem is that EF is auto generated – so you can’t just make an interface and have it implement it.

image

This is the problem I solved at the code camp 2 years ago (Note that this would be so much easier if MSFT added interfaces to their auto generated classes.  Just sayin’).  In any event, the way around it is to use a partial class and then extract the interface from that partial class.  To that end, I added a new class to the project with the following code:

public partial class NorthwindEntities 
{

}

I then used Refactor –> Extract Interface and I got an interface:

interface INorthwindEntities
{
System.Data.Entity.DbSet<Category> Categories { get; set; }
System.Data.Entity.DbSet<CustomerDemographic> CustomerDemographics { get; set; }
System.Data.Entity.DbSet<Customer> Customers { get; set; }
System.Data.Entity.DbSet<Employee> Employees { get; set; }
System.Data.Entity.DbSet<Order_Detail> Order_Details { get; set; }
System.Data.Entity.DbSet<Order> Orders { get; set; }
System.Data.Entity.DbSet<Product> Products { get; set; }
System.Data.Entity.DbSet<Region> Regions { get; set; }
System.Data.Entity.DbSet<Shipper> Shippers { get; set; }
System.Data.Entity.DbSet<Supplier> Suppliers { get; set; }
System.Data.Entity.DbSet<Territory> Territories { get; set; }
}

I then changed my unit test code to use the interface like so:

[TestMethod]
public void GetTerritoryForARegionIdWithRegionIdOne_ReturnsThreeRecords()
{
    TerritoryFactory factory = new TerritoryFactory();
    INorthwindEntities entities = new NorthwindEntities();
    factory.NorthwindEntities = entities;
    List<Territory> territories = factory.GetTerritoriesForARegionId(1);

    Int32 expected = 3;
    Int32 actual = territories.Count;

    Assert.AreEqual(expected, actual);
}

When I ran the test, I got the same red (red>green>refactor?  how about red > redder > refactor).

image

So the last thing is the implementation.  How do we build a “fake” in memory instance of the Northwind Entities that returns 3 Territories?  Enter Mocking Framework!

image

 

And then switch out the implementation for the Mock:

[TestMethod]
public void GetTerritoryForARegionIdWithRegionIdOne_ReturnsThreeRecords()
{
    TerritoryFactory factory = new TerritoryFactory();

    //Replace the actual implementation with the Fake
    //INorthwindEntities entities = new Tff.NorthwindApp.NorthwindEntities();
    INorthwindEntities entities = new Fakes.StubNorthwindEntities();

    //Add in Stub Data
    entities.Territories.Add(new Territory { TerritoryID = "1", RegionID = 1 });
    entities.Territories.Add(new Territory { TerritoryID = "2", RegionID = 1 });
    entities.Territories.Add(new Territory { TerritoryID = "3", RegionID = 1 });

    factory.NorthwindEntities = entities;
    List<Territory> territories = factory.GetTerritoriesForARegionId(1);
    Int32 expected = 3;
    Int32 actual = territories.Count;

    Assert.AreEqual(expected, actual);

}

I half expected that running this would get green.  I assumed that the default constructor of EF (which is what the Mocking framework would use) would just give an empty graph without going to the database.  Alas, I was wrong:

image

So the Stub is still going out to the database.

clip_image001

I then spent a couple of hours of trying to get around this “feature” of the EF being so tightly coupled to the database and I gave up.  I then tried the same technique with Linq to Sql.  Unfortunately, I ran into the same problem.  I then went to stack overflow and got nothing.

To me, this is a real limitation of EF.  EF should be able to be stubbed easily.  MSFT missed a real opportunity here…

The Annotated Turing

Based on Bob Martin’s recommendation in his Clean Coder’s webcast, I picked up The Annotated Turing by Charles Petzold. 

image

What a fun read!  Petzold really does a good job of breaking down the original paper into manageable chunks – and gives just enough background to place the paper’s ideas in context.  I really had fun digging though my gray cells of the difference among the different kids of numbers (real, imaginary, etc…) .  I am about half way through the book  and I plan to re-read it once I finish it.  If you work in IT for a living, this is worth a read – and re-read….

Town Of Cary ISAB

I was reappointed to a second term on the Town Of Cary’s Information Services Advisory Board (ISAB).  Not only that, I was made chair:

image

http://www.townofcary.org/Assets/Staff+Reports/2012+Recommended+Board+Appointments.pdf

Panzer Redux: WinRT

I was thinking of porting the Windows7 game that I created onto Windwos RT.  Since they are both XAML based, I thought it would be a snap.  I thought wrong.  Part of the problem is that I wrote the original game with poor architecture.  The other part of the problem is that Windows RT makes it hard to port existing code.

I first wanted to separate the game interface from the core game functions.  I created a new project and brought in all of the non-graphical components:

image

 

The problem is that every actor seems to have a dependency on the Game class.  For example:

image

 

So I need to break the dependencies between these factories and their implementation.  I decided on Property Injection versus constructor injection as a matter of convention because I am not sure on the number of dependencies for each factory and I hate really long constructors.  So my refactoring looks like:

public class ArmyFactory
{
    public ScenarioFactory ScenarioFactory { get; set; }
    public UnitFactory UnitFactory { get; set; }

    public ArmyInfo CreateArmy(int scenarioId, int sideId)
    {
        ArmyInfo armyInfo = new ArmyInfo();
        armyInfo.SideId = sideId;

        List<ScenarioUnit> scenarioUnits = ScenarioFactory.ScenarioUnitFactory.GetScenarioUnits(scenarioId);
        foreach (ScenarioUnit scenarioUnit in scenarioUnits)
        {
            int unitId = 0;
            if (scenarioUnit.SideId == sideId)
            {
                armyInfo.Units.Add(UnitFactory.CreateUnit(unitId, scenarioUnit));
                unitId++;
            }
        }

        return armyInfo;
    }
}

I then was confronted with the fact that my game engine has dependencies on Windows Phone:

image

Looking at the original code:

image

So I need a way of loading from an XML file – or do I?  What if the EquipmentClass data was stored in something other than XML?  Do I really want my factory breaking?  I then looked at ScenarioTile – I had loaded data from either a web service or from an XML file.

I then realized that the factory is a translator –>  In goes XML, SOAP, ADO.NET recordset, whatever, out always pops the instantiated objects.  XML was used because that is the de-facto standard for Win Phones.  I also see that my Lookup data is in XML.  Therefore, what I need is a platform-agnostic XML Stream Reader.  Unfortunately, that is not in the cards: Windows Phone has its implementation, System.IO has its implementation, and Windows 8 RT has its implementation.   I then refactored the factory to take in an XML file of a certain structure and spit out the classes.  All of the implementation that is platform specific I removed.

image

So where do I implement the actual XML load?  In the calling application.  Windows Phone 7.x uses XElement, WindowsRT does, and I have to assume Windows Phone 8 does too.  I wonder if all platforms shared the same serialization implementation? 

Ugh!  looks like I picked the wrong week to quit drinkin

Web && App sub-config files

One of the cool features of VS2010 and web deploy is the ability to have sub-config files.  that way you don’t have to comment out (and remember) sections of your web .config for each environment.  You get this feature out of the box with web.config files when you create a new web project:

 

 image

In the master web.config, you pretty much have the same as your normally do:image

In the Sub-Config file, you put in the updated value and some special xsd syntax:

image

When you publish the website, you only have 1 web.config file. What happens is that the sub-config files have their values moved into the master web.config. For example, if you put a Debug connection String in the Web.Debug.Config, that entry is copied into the master web.config.

When you publish with the Solution Configuration set to Debug:

image

Your Web.Config gets updated:

image

Note that if you run the website locally inside Visual Studio (Hitting F5), it does not transform because you are not publishing. You need to publish to implement the change.

A good article is this one and a good webcast is here.

But what about app.configs?  Good question – because this is based on web deploy, you don’t get this feature in an out of the box desktop project.  There are two good posts that explain how to update your projects so they support app configs.  The most concise is this one.  The problem is that it is incomplete, After you follow Phil’s changes to the project file, you also need to follow this posts on how to update you sub-config to use the xdt.  For example:

image

Once you do that, you get the master app.config updated.  The other cool thing is that you don’t have to use any kind of publishing – hit F5 and the .config in your target environment folder is crated appropriately.

Cary Technology Task Force

I was recently appointed to the Town Of Cary’s technology task force: http://carycitizen.com/2012/07/31/cary-names-tech-task-force/

Rotating a Signature: Part 2

I know the center point and I need to rotate every point of the signature around the center point as the centerline rotates. I established the center point in this blog post.

image

Replacing the black dots with some letters, I have this:

image

Where Line AC is the same distance as Line A’C.  They are 2 points on a circle around C with the line as the radius:

image

In addition, you can drop a vertical line from A until its Y equals the Y in the center line.  The distance between LineAB is then known – the difference in Y from the center line that shares the same X Coordinate.

image

Now that the length of LineAC and LineAB is known, the LineBC can be calculated using the Pythagoram theorem.

Then, the A can be moved along its arc with LineAB and LineBC kept constant.  The rotation stops when the Y of Point B is equal to the Y of the horizontal line.

image

 

At least, that it what I think.  I started with a simple test for the distance:

[TestMethod()]
[DeploymentItem("Tff.Signature.Comparison.dll")]
public void GetDistanceBetweenTwoPoints_SamePoints_ReturnsZero()
{
    ScatterplotComparisonFactory_Accessor target = new ScatterplotComparisonFactory_Accessor();
    Point pointOne = new Point(1, 1);
    Point pointTwo = new Point(1, 1);
    Double expected = 0.0;
    Double actual = target.GetDistanceBetweenTwoPoints(pointOne, pointTwo);
    Assert.AreEqual(expected, actual);
}

I then wrote my function:

private Double GetDistanceBetweenTwoPoints(Point pointOne, Point pointTwo)
{
    Int32 differenceBetweenXs = pointOne.X - pointTwo.X;
    Int32 differentBetweenYs = pointOne.Y - pointTwo.Y;
    Double differenceBetweenXsSquared = differenceBetweenXs * differenceBetweenXs;
    Double differentBetweenYsSquared = differentBetweenYs * differentBetweenYs;
    Double SumOfXandYSquared = differenceBetweenXsSquared + differentBetweenYsSquared;
    return Math.Sqrt(SumOfXandYSquared);
}

It ran green so I added some additional tests – and they were also green to go

[TestMethod()]
[DeploymentItem("Tff.Signature.Comparison.dll")]
public void GetDistanceBetweenTwoPoints_SameX_ReturnsExpected()
{
    ScatterplotComparisonFactory_Accessor target = new ScatterplotComparisonFactory_Accessor();
    Point pointOne = new Point(1, 1);
    Point pointTwo = new Point(1, 2);
    Double expected = 1.0;
    Double actual = target.GetDistanceBetweenTwoPoints(pointOne, pointTwo);
    Assert.AreEqual(expected, actual);
}

[TestMethod()]
[DeploymentItem("Tff.Signature.Comparison.dll")]
public void GetDistanceBetweenTwoPoints_DifferentXAndY_ReturnsExpected()
{
    ScatterplotComparisonFactory_Accessor target = new ScatterplotComparisonFactory_Accessor();
    Point pointOne = new Point(1, 4);
    Point pointTwo = new Point(4, 0);
    Double expected = 5.0;
    Double actual = target.GetDistanceBetweenTwoPoints(pointOne, pointTwo);
    Assert.AreEqual(expected, actual);
}

Now that I have AC, I need to calculate AB.  I looked at my test and realized I already have the calculation – all I have to is fine the point on the center line whose Y matches point A’s Y.  That will be the subject of my next post…

Rotating a Signature: Part 1

For the next step of my signature analysis, I need to rotate the signatures so that both the compared and the comparee signatures are on the same horizontal plain.  To rotate the signatures, I need to find the center line (which I did in this blog post)  and then rotate that line to horizontal with all of the signature’s points keeping the exact same relationship to the center line.

image

To that end, I need to find the center point of the signature.  I created my first unit test like this:

[TestMethod()]
[DeploymentItem("Tff.Signature.Comparison.dll")]
public void GetCenterPoint_OddNumberOfPoints_ReturnsCenterPoint()
{
    ScatterplotComparisonFactory_Accessor target = new ScatterplotComparisonFactory_Accessor();
    List<Point> points = new List<Point>();
    points.Add(new Point(0, 0));
    points.Add(new Point(1, 1));
    points.Add(new Point(2, 2));

    Point expected = new Point(1,1);
    Point actual = target.GetCenterPoint(points);
    Assert.AreEqual(expected, actual);
}

I then wrote enough production to pass this test:

private Point GetCenterPoint(List<Point> comparePoints)
{
    Int32 totalX = 0;
    Int32 totalY = 0;
    Int32 totalCount = 0;

    foreach (Point point in comparePoints)
    {
        totalX += point.X;
        totalY += point.Y;
        totalCount += 1;
    }

    Int32 averageX = (Int32)(totalX / totalCount);
    Int32 averageY = (Int32)(totalY / totalCount);

    return new Point(averageX, averageY);
}

Sure enough: GreenToGo:

image

I then wrote a test for a list of 4 points and quickly realize that I can’t calculate the center point for a list that contains an even-number of points:

image

Sounds like an exception to me.  I altered the test like so

[TestMethod()]
[DeploymentItem("Tff.Signature.Comparison.dll")]
[ExpectedException(typeof(ArgumentException))]
public void GetCenterPoint_EvenNumberOfPoints_ThrowsArgumentException()
{
    ScatterplotComparisonFactory_Accessor target = new ScatterplotComparisonFactory_Accessor();
    List<Point> points = new List<Point>();
    points.Add(new Point(0, 0));
    points.Add(new Point(1, 1));
    points.Add(new Point(2, 2));
    points.Add(new Point(3, 3));

    Point actual = target.GetCenterPoint(points);
    Assert.Fail("Should not get here.");
}

and then the production code:

private Point GetCenterPoint(List<Point> comparePoints)
{
    if (comparePoints.Count % 2 == 0)
    {
        throw new ArgumentException("comparePoints must have an even number.");
    }

    Int32 totalX = 0;
    Int32 totalY = 0;
    Int32 totalCount = 0;

    foreach (Point point in comparePoints)
    {
        totalX += point.X;
        totalY += point.Y;
        totalCount += 1;
    }

    Int32 averageX = (Int32)(totalX / totalCount);
    Int32 averageY = (Int32)(totalY / totalCount);

    return new Point(averageX, averageY);
}

And I was greentogo.

So then I thought – what about a line where the center point is not included in the list?

[TestMethod()]
[DeploymentItem("Tff.Signature.Comparison.dll")]
[ExpectedException(typeof(ArgumentException))]
public void GetCenterPoint_OddNumberOfNonConsecutivePoints_ReturnsCenterPoint()
{
    ScatterplotComparisonFactory_Accessor target = new ScatterplotComparisonFactory_Accessor();
    List<Point> points = new List<Point>();
    points.Add(new Point(0, 0));
    points.Add(new Point(1, 1));
    points.Add(new Point(2, 2));
    points.Add(new Point(5, 5));
    points.Add(new Point(6, 6));

    Point expected = new Point(3, 3);
    Point actual = target.GetCenterPoint(points);
    Assert.AreEqual(expected, actual);
}

I got Red

image

The problem is that list of points that I am using to represent the line may or may not include the true center point.  But that is not the center points problem – its only job is to tell me the center point for an odd number of points.  The problem is that there is a rounding assumption in the code – 1/2 way between 0 and 6 is three – the values of the other numbers are irrelevant.  I then refactored the GetCenterPoint like so:

private Point GetCenterPoint(List<Point> comparePoints)
{
    if (comparePoints.Count % 2 == 0)
    {
        throw new ArgumentException("comparePoints must have an odd number.");
    }

    Point lowestPoint = comparePoints.Min();
    Point highestPoint = comparePoints.Max();

    Double MidX = (highestPoint.X + lowestPoint.X)/2;
    Double MidY = (highestPoint.Y + lowestPoint.Y)/2;

    Int32 MidXRounded = (Int32)MidX;
    Int32 MidYRounded = (Int32)MidY;
    return new Point(MidXRounded, MidYRounded);
}

And I was GreenToGo.

I then realized that GetCenterPoint implicitly violates the SRP – it doesn’t matter if there is a even or odd number in the compare points – just as long as there is at least 1 point.  The even/odd is only if I want to see if the center point of the line is in the list of points that I am using to represent the line.  That is another function – and another set of tests.  I refactored the GetCenterPoint like this:

if (comparePoints.Count == 0)
 {
     throw new ArgumentException("comparePoints has no points.");
 }

And changed my ArguementExceptionTest:

[TestMethod()]
[DeploymentItem("Tff.Signature.Comparison.dll")]
[ExpectedException(typeof(ArgumentException))]
public void GetCenterPoint_NoPointsInArgument_ThrowsArgumentException()
{
    ScatterplotComparisonFactory_Accessor target = new ScatterplotComparisonFactory_Accessor();
    List<Point> points = new List<Point>();
    Point actual = target.GetCenterPoint(points);
    Assert.Fail("Should not get here.");
}

And I was still green everywhere.  With the center point established, I was ready to tackle the rotation of the points around that center point.

Why you should never use code from MSDN

I think part of the problem with bad code is the habit to copy/paste samples from MSDN.

For example, consider this example.

Explanatory Comments

image

I agree that Microsoft should put explanatory comments into the code – the code is a sample on how to do something.   The problem is that someone who doesn’t know better will copy/paste the entire block into their solution.  I think Microsoft could help its developers by putting a provision at the top of the sample:

image

The cynic in me would then expect to see that warning also copy/pasted into someone’s project.  Perhaps the copy/paste button on the page could filter the comments.

Big Blocks Of Code

Another problem with the MSDN code “as-is” is that the code is one big block – there are three classes put into 1 block.  It wouldn’t kill Microsoft to put each class into their own block.  The MSDN explanations could then be broken up and when you copy/paste the code, you only get 1 class at a time.  As it stands, all of the explanations is in 1 big paragraph at the top of the 1 big code sample.  A step by step approach might be more helpful – and promote better code.

Constructor Chaining

Finally, MSDN doesn’t chain the constructors of the example. 

public UrlConfigElement(String name, String url)
{
    this.Name = name;
    this.Url = url;
}

public UrlConfigElement()
{

    this.Name = "Contoso";
    this.Url = "http://www.contoso.com";
    this.Port = 0;
}

Should be

public UrlConfigElement(String name, String url)
{
    this.Name = name;
    this.Url = url;
    this.Port = 0;
}

public UrlConfigElement()
    : this("Contoso", "http://www.contoso.com")
{
    
}



That is just sloppy coding and should be fixed…

Property Assignment

I am a big fan of separation of concerns and layering when it comes to application architecture.  Using a dedicated service layer means that all client/calling layers are insulated from all dependencies past the service layer.  In a usual n-tier architecture, that means that the layer(s) calling the service layer have no idea about the data tier behind the service.

Because of that, you can not use the concrete classes from the permanent data store as the data structures that carry data among the layers.  Enter in the EF POCO generator!  Using this add-in, you get EF integrated POCOs that are already WCF-ifed.

The downside is the update (or so I thought on Friday) – because you are using a different instance between service calls, you have to rehydrate a new object, assign in the new values, and then persist.  This is very much the problem of EF classes when EF came out.

So I created a test project to see if I could use System.Reflection to help me do that assignment.  I created a project with the following two classes:

public class Person
{
    public int PersonId { get; set; }
    public String PersonName { get; set; }
}
public class Student: Person
{
    public String SchoolName { get; set; }
}

Following TDD, I created a Test Project with the following test:

[TestMethod()]
public void CreateStudentFromPerson_PersonNameAssigns_Test()
{
    Person person = new Person();
    person.PersonId = 0;
    person.PersonName = "Test";

    StudentFactory studentFactory = new StudentFactory();
    Student student = studentFactory.CreateStudentFromPerson(person);

    string expected = person.PersonName;
    string actual = student.PersonName;

    Assert.AreEqual(actual, expected);
}

I then implemented the factory:

public Student CreateStudentFromPerson(Person person)
{
    Student student = new Student();

    PropertyInfo[] personPropertyInfos = typeof(Person).GetProperties();
    PropertyInfo[] studentPropertyInfos = typeof(Student).GetProperties();

    PropertyInfo studentPropertyInfo = null;
    foreach (PropertyInfo personPropertyInfo in personPropertyInfos)
    {
        studentPropertyInfo = studentPropertyInfos.FirstOrDefault(spi => spi.Name == personPropertyInfo.Name);
        if (studentPropertyInfo != null)
        {
            object personValue = personPropertyInfo.GetValue(person, null);
            studentPropertyInfo.SetValue(student, personValue, null);
        }
    }
    return student;
}

Sure enough, the test ran green.

I then wanted to implement a generic method that would assign property values over regardless of the types in the arguments:

public Student CreateStudentFromPerson(Person person)
{
    Student student = new Student();
    return (Student)AssignObjectPropertyValues(person, student);
}

public Object AssignObjectPropertyValues(Object baseObject, Object targetObject)
{
    PropertyInfo[] basePropertyInfos = baseObject.GetType().GetProperties();
    PropertyInfo[] targetPropertyInfos = targetObject.GetType().GetProperties(); ;

    PropertyInfo targetPropertyInfo = null;
    foreach (PropertyInfo basePropertyInfo in basePropertyInfos)
    {
        targetPropertyInfo = targetPropertyInfos.FirstOrDefault(spi => spi.Name == basePropertyInfo.Name);
        if (targetPropertyInfo != null)
        {
            object basePropertyValue = basePropertyInfo.GetValue(baseObject, null);
            targetPropertyInfo.SetValue(targetObject, basePropertyValue, null);
        }
    }

    return targetObject;
}

And wouldn’t you know: Green to go <trademark pending>!

image

MSDN warns about the performance cost, but I have to believe that my compiler is so good that there is negligible difference.

So then there was one more requirement, all Strings needed to be encrypted.  I created another test like so:

[TestMethod()]
public void CreateStudentFromPerson_PersonNameAssignsEncrypted_Test()
{
    Person person = new Person();
    person.PersonId = 0;
    person.PersonName = "Test";

    StudentFactory studentFactory = new StudentFactory();
    Student student = studentFactory.CreateStudentFromPerson(person,true);

    string expected = "XXXXX";
    string actual = student.PersonName;

    Assert.AreEqual(actual, expected);
}

with the “XXXXX” serving as a proxy for the actual encryption.

I then overloaded the method in the factory like so:

public Object AssignObjectPropertyValues(Object baseObject, Object targetObject, Boolean useEncryption)
{
    PropertyInfo[] basePropertyInfos = baseObject.GetType().GetProperties();
    PropertyInfo[] targetPropertyInfos = targetObject.GetType().GetProperties(); ;

    PropertyInfo targetPropertyInfo = null;
    foreach (PropertyInfo basePropertyInfo in basePropertyInfos)
    {
        targetPropertyInfo = targetPropertyInfos.FirstOrDefault(spi => spi.Name == basePropertyInfo.Name);
        if (targetPropertyInfo != null)
        {
            object basePropertyValue = basePropertyInfo.GetValue(baseObject, null);
            if (targetPropertyInfo.GetType() == typeof(String) && useEncryption)
            {
                targetPropertyInfo.SetValue(targetObject, "XXXXX", null);
            }
            else
            {
                targetPropertyInfo.SetValue(targetObject, basePropertyValue, null);
            }
        }
    }

    return targetObject;
}

and had the original method chain:

public Student CreateStudentFromPerson(Person person, Boolean useEncryption)
{
    Student student = new Student();
    return (Student)AssignObjectPropertyValues(person, student, useEncryption);
}

My test ran red:

image

Going back to the factory, I change the if condition to this:

if (targetPropertyInfo.PropertyType.Name == "String" && useEncryption)

And I was green to go <trademark pending>.

I then realized that Bob Martin would yell at me because I have boolean arguments.  I then created an interface called IEncryptable like so:

public interface IEncryptable
{
    Boolean IsEncrypted { get; set; }
}

I then adjusted my method signatures to remove the boolean argument.

public Student CreateStudentFromPerson(Person person)
{
    Student student = new Student();
    return (Student)AssignObjectPropertyValues(person, student);
}

and adjusted the AssignObjectPropertyValues to check if the targettype implements IEncryptable:

object basePropertyValue = basePropertyInfo.GetValue(baseObject, null);
 Type targetObjectType = targetObject.GetType();
 if(targetObjectType.GetInterfaces().Contains(typeof(IEncryptable)))
 {
     if (targetPropertyInfo.PropertyType.Name == "String")
     {
         targetPropertyInfo.SetValue(targetObject, "XXXXX", null);
     }
 }
 else
 {
     targetPropertyInfo.SetValue(targetObject, basePropertyValue, null);
 }

Sure enough, the Encrypt Unit test passed but the unencrypt did not

image

Time to refactor!  I added in a check for IEncryptable like so

if(targetObjectType.GetInterfaces().Contains(typeof(IEncryptable)))
{
    PropertyInfo encryptedPropertyInfo = targetPropertyInfos.FirstOrDefault(tpi => tpi.Name == "IsEncrypted");
    Boolean isEncrypted = (Boolean)encryptedPropertyInfo.GetValue(targetObject,null);

    if (isEncrypted)
    {
        if (targetPropertyInfo.PropertyType.Name == "String")
        {
            targetPropertyInfo.SetValue(targetObject, "XXXXX", null);
        }
        else
        {
            targetPropertyInfo.SetValue(targetObject, basePropertyValue, null);
        }
    }
    else
    {
        targetPropertyInfo.SetValue(targetObject, basePropertyValue, null);
    }
}
else
{
    targetPropertyInfo.SetValue(targetObject, basePropertyValue, null);
}

and I was green to go.  I then noticed all of the nested if..thens and realized I should make some additional classes – EncryptedStudent perhaps.  That would cut down on the cyclomic complexity.

After all that, I was informed of the ApplyCurrentValues method.  This makes the application part of my solution useless – but not the encryption…