I’ve been writing some unit tests lately that require quite a bit of casting. This gets tiring pretty fast so I went ahead and decided to give the dynamic keyword a try. I’ll show the before and after examples and let you decide.
Here is the non-dynamic version.
[Test]
public void InvokeWithAddPlusInvokeTest()
{
string code = "f(1 + 2) + g()";
var b1 = (BinaryExpression)this.pipeline.Compile(code);
var f = (MethodInvokeExpression)b1.Left;
var g = (MethodInvokeExpression)b1.Right;
var b2 = (BinaryExpression)f.Parameters.Single();
var one = (PrimitiveExpression)b2.Left;
var two = (PrimitiveExpression)b2.Right;
Assert.That(b1.Operator == BinaryOperator.Add);
Assert.That(b2.Operator == BinaryOperator.Add);
Assert.That(((ReferenceExpression)f.Target).Name == "f");
Assert.That(((ReferenceExpression)g.Target).Name == "g");
Assert.That(one.Value == "1");
Assert.That(two.Value == "2");
}
In this test I am compiling an expression into an AST and digging around to verify that the correct nodes were created in the right places in the tree.
Here is the dynamic version.
[Test]
public void InvokeWithAddPlusInvokeTest()
{
string code = "f(1 + 2) + g()";
dynamic b1 = this.pipeline.Compile(code);
dynamic b2 = Enumerable.Single(b1.Left.Parameters);
Assert.That(b1.Operator == BinaryOperator.Add);
Assert.That(b2.Operator == BinaryOperator.Add);
Assert.That(b1.Left.Target.Name == "f");
Assert.That(b1.Right.Target.Name == "g");
Assert.That(b2.Left.Value == "1");
Assert.That(b2.Right.Value == "2");
}
A lot shorter that’s for sure. The only downside is that if I change the nodes I will no longer get compile time warnings… but I will get unit test errors so this shouldn’t theoretically matter. I also no longer get intellisense so I either have to just know the structure of the objects or use the debugger to figure it out. Still the simplicity is looking good.