TDD with C# 4 dynamic keyword

*Updated* 2 Mai 2011: The "dynamic" keyword in C#4 was not meant to be used in the below scenario. Use VS2010 code completion instead.


We know that if you are using TDD, then you should write your test before you are implementing anything else, don’t we :-)
image
Figure: 1. Write a failing test (red), 2. Make the test pass (green), 3. Refactor your code

But if you are thinking about new methods, you can’t really run the tests because your unit test wont compile, see the following example.

 

[TestMethod()]
        public void CalculatorThingAdd_2PositiveNumbers_ResultAdded()
        {
            // Arrange
            CalculatorThing myCalculator = new CalculatorThing();
            int result = 0; 
            int expcected = 3;

            // Act
            result = myCalculator.Addition(1, 2);
            
            // Assert
            Assert.AreEqual(result, expcected);

        }

ap--delete BAD code example: In TDD I would like to run this test, before I implement the method “Addition”

 

On compiling this test, you get the following error message

Error    1    'ConsoleApplication.CalculatorThing' does not contain a definition for 'Addition' and no extension method 'Addition' accepting a first argument of type 'ConsoleApplication.CalculatorThing' could be found (are you missing a using directive or an assembly reference?)   

 image
ap--delete Figure: Code want compile, because “Addition” is not implemented, and C# is static type safe on compile time

 

But you can avoid this by using the dynamic keyword, see below

 

 

[TestMethod()]
        public void CalculatorThingAdd_2PositiveNumbers_ResultAdded()
        {
            // Arrange
            dynamic myCalculator = new CalculatorThing();
            int result = 0; 
            int expcected = 3;

            // Act
            result = myCalculator.Addition(1, 2);
            
            // Assert
            Assert.AreEqual(result, expcected);

        }

apcheck_thumb1 GOOD code example: This code compiles nicely

 

 

image
apcheck_thumb1 Figure: Code compiles, because myCalculator is a dynamic object and evaluated on runtime not on compile time

 

But if you run this test you get:

image
Figure: Test failed because method not implement

Test method CalculatorConsole.Tests.CalculatorTest.CalculatorThingAdd_2PositiveNumbers_ResultAdded threw exception:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'ConsoleApplication.CalculatorThing' does not contain a definition for 'Addition'

 

NICE!!!!
We have a failing test! 
image

Now go and implement the method and make the test pass!
image

5 comments:

Unknown said...

Hi Peter,
this is a very interesting approach. I hate to have to go to the class and to create methods with "return null;"
or
"throw new NotImplementedException();"
I'm looking forward to C# 4.0 and Visual Studio 2010 :-)

Anonymous said...

Nice, takes a little of the pain out of testing.

Rainer Hilmer said...

I don't see any benefit from this. You have to implement the method anyway and afterwards you even would have to modify the test in order to get rid of this fake behavior.
You first write the test and let the code completion feature create the method. Run the test to see whether everything is connected as it should be (could become green if not). Then fill the method with life and run the test again. That's what TDD is all about.
In case you develop a multi-component architecture, use a mocking framework to simulate behaviors of components which do not exist yet.

Robgert Mischke said...

This not like TDD is ment. According to the examples of Kent Beck (the TDD "inventor"), create a real method und let it fail.

Peter Gfader said...

@Robgert and @Rainer
Agree!

I had the idea that this could be a good usage of dynamic types.
Because the types that we are testing, don't have the needed behavior yet...

As Rainer said, I don't like the approach either, to go back and change "dynamic" to the implementation type.

Post a Comment

Latest Posts

Popular Posts