Friday, November 28, 2014

UnitTesting with DateTime.Now

Today I needed to unit test a component which uses System.DateTime.Now (C# .NET) ...

The good answer:this actually works using System.Fakes (sorry, no idea in which edition, but in ultimate it works perfectly). In the past microsoft seemed to use "moles" (see: http://research.microsoft.com/en-us/projects/moles/ ) instead of "fakes".

Using fakes:

  • Create a Unit-Test Project
  • Select References
  • Right-Click on "add fakes assembly" 
    • this adds ref to "...Fakes.dll"
    • Fakes Folder with xml stuff
  • now you enabled fakes for system (most of the time mscorlib will be faked too by VS)... 
  • start to use it


Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
        [TestMethod]
        public void CheckCurrentDate_ResultFixed2012()
        {
            // Arrange
            using (ShimsContext.Create())
            {
                // Act
                System.Fakes.ShimDateTime.NowGet = () => new DateTime(2012, 12, 31);

                // Assert
                Assert.AreEqual(2012, DateTime.Now.Year);
            }
        }


Kind regards, Daniel

Thursday, November 6, 2014

Expression Trees: good ideas and bad ideas

Today I had a look at expression trees. There are some really cool solutions using expression trees, which make the world of developers a better place.

I focused on the usage in combination with PropertyChanged where we have a lot to do with constant ("magic") strings which refer to the calling property name. In standard WPF projects we put this RaisePropertyChanged - boiler plate code like in the example http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx in every setter of a property.

A new and modern possible solution as used in

is to work with expression trees. 


The concept is:
  • still use caller member name if possible
  • make a lambda function which has only 1 expression tree leaf: the property.
  • push the lambda function as parameter inside (as expression tree)
  • In the expression tree read the name of the property which is handed in and use its name as string like in the original way
The function to read the described expression tree is quite simple (as shown in http://stackoverflow.com/questions/671968/retrieving-property-name-from-lambda-expression/2916344#2916344 ) . The following example code shows how it works:

1
2
3
4
5
6
        private string GetMagicString(Expression<Func<object>> exp) 
        {
         
            return (exp.Body as MemberExpression ??
                ((UnaryExpression)exp.Body).Operand as MemberExpression).Member.Name;
        }

Important here is:

The difference is that you will get a UnaryExpression if your expression represents a value type whereas you will get a MemberExpression if your expression represents a reference type.

So you can call GetMagicString(() => MyProp) and get back MyProp as string.

This is a good idea, because now you get a compile error if you mistype your input. Quite cool.

Attention! You can implement magic strings with expression trees too and have the same problem as mentioned before. 


1
2
3
            MessageBox.Show(
                PrintStaticInfo(
                    (machinename) => string.Format("{0} is the machine name", machinename)));

You see we use machinename as parametername and push this expression tree into method PrintStaticInfo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
        private string PrintStaticInfo(Expression<Func<string,string>> expression)
        {
            string value = string.Empty;
            switch (expression.Parameters[0].Name.ToLower())
            {
                case "username":
                    value = Environment.UserName;
                    break;
                case "machinename":
                    value = Environment.MachineName;
                    break;
            }
            return expression.Compile()(value);
        }

This function inserts the value for a given parameter by name. The parameter name if mistyped breaks exactly the same way as PropertyChanged does if the wrong property name was inserted. Ugly code, different ways :-).

kind regards, Daniel