Why Typemock-Isolator for TDD?
There is a long discussion in the ALT.NET group about TDD and Typemock, it is very interesting and I suggest that you read the thread.
Benefits of TDD
Although the benefits of using TDD are inconclusive, here are some benefits attributed to using TDD:
- Developers write more tests
- Tests use the API, so developers can get early feedback on the API design
- Developers have more Focus as the tasks are divided into small chunks
Why do we need to Mock?
In order to use TDD effectively the tests must
-
Run fast.
-
Run in isolation.
-
Self Contained.
-
Race Safe.
-
Independent.
In order to make sure that we have fast tests, that the tests are self contained and don’t rely on external resources, we need to test our code in isolation from the rest of the system. This is done by mocking out components that are not part of our test, and testing only the unit logic.

TDD and Typemock-Isolator
So where does Typemock-Isolator fit in and how does it compare to other frameworks?
When using TDD with legacy code or 3rd party libraries, the benefits of Typemock-Isolator are well known, so I will not talk about those area’s but about green-field projects.
Developing with Typemock-Isolator, developers will be able to do all the stuff the other frameworks and manual mocks/stubs allow with the addition of being able to mock static methods, private methods and types and a chain of calls (fluent interfaces) in one go (As well as better integration with Visual Studio).
These features make it simpler to divide the code into small chunks – leading to more focus and more tests.
The API’s are still reviewed as tests are written using the API so early feedback of the API’s are part of this process. This is achieved with the freedom to use any internal design of the unit: Extension Methods, Linq, Fluent interfaces, Singletons and Factories.
Other frameworks will force the developer to use DI as an internal pattern. This might be good, but might not be good. It might leave public API’s that where not meant to be public. It will leave the ability to inject an alternative implementation that might ruin the system. It will probably lead to developing extra functionality to support validating and error handling of the injected components. This might be a YAGNI smell that will require extra development and tougher maintenance. Is DI a silver bullet design pattern? Or do you want the Freedom to refactor the code to best suit the product – I know that I do, this is what Typemock-Isolator will give: The benefits of TDD with the freedom to refactor your code to any design.
Dependency Injection with TypeMock
The has been some buzz about Dependency Injection lately (here is another thread). But I want to actually show how TDD with TypeMock can lead to a DI solution, and how the tests will step by step naturally lead to the DI solution when the business features require it.
Lets start with a very simple example that displays an error message in a Windows Message Box. This is a requirement from the customer, just to make things simple we have a ValidateThatNameIsOk() method that displays a Message when the Name is empty.
Part 1 – Initial Code
Listing 1 – the test.
[Test]
public void ValidateThatNameIsOk_Passes_WhenNameExists()
{
SomeApplication classUnderTest = new SomeApplication();
classUnderTest.ValidateThatNameIsOk(“r”);
}
Listing 2 – the simplest solution
public void ValidateThatNameIsOk(string name)
{
}
Now lets add a failing case (we must mock out the MessageBox or we will halt the test)
Listing 3 – another test.
[Test,VerifyMocks]
public void ValidateThatNameIsOk_Fails_WhenNameIsEmpty()
{
// Record Mocks
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
MessageBox.Show(“A Name must be entered“);
recorder.Return(DialogResult.OK);
}
SomeApplication classUnderTest = new SomeApplication();
classUnderTest.ValidateThatNameIsOk(“”);
}
Listing 4 – and here is the simplest solution.
public void ValidateThatNameIsOk(string name)
{
if (name.Length==0)
{
MessageBox.Show(“A Name must be entered”);
}
}
Part 2 – More Features Request
Our application is a success and we managed to deliver on time (because we didn’t write unneeded code). After some time our customer asked for a new feature: “run the application in batch mode”. Now we cannot use MessageBox.Show() any more. Now we need to write the message to the console (or a file).
Lets start with the test*.
Listing 5
[Test,VerifyMocks]
public void ValidateThatNameIsOk_FailsAndWritesToConsole_WhenNameIsEmpty()
{
// Record Mocks
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
Console.WriteLine(“A Name must be entered”);
recorder.CheckArguments();
}
SomeApplication classUnderTest = new SomeApplication();
classUnderTest.ValidateThatNameIsOk(“”);
}
Part 3 – First Solution, inline-condition
private bool useConsole = false;
public bool UseConsole
{
set { useConsole = value; }
}
public void ValidateThatNameIsOk(string name)
{
if (name.Length==0)
{
if (useConsole)
Console.WriteLine(“A Name must be entered”);
else
MessageBox.Show(“A Name must be entered”);
}
}
Part 4 – Extract the Message Class
public class Message
{
private static bool useConsole = false;
public static bool UseConsole
{
set { useConsole = value; }
}
public static void Show(string message)
{
if (useConsole)
Console.WriteLine(“A Name must be entered”);
else
MessageBox.Show(“A Name must be entered”);
}
}
and here is the validation method.
public void ValidateThatNameIsOk(string name)
{
if (name.Length==0)
{
Message.Show(“A Name must be entered”);
}
}
Our Console test (and the batch runner) will need to call Message.UseConsole = true and all our tests will pass.
Now we need to add a feature to write the message to an external file.
Part 5 – Add another output stream and Polymorphism
To add another output stream (a log file for example), we would write a test which will lead to a change in the Message class, the simplest way is to change the boolean to an enumerator and change the if statement to a switch,
private static MessengerType messenger = MessengerType.MessageBox;
public static MessengerType Messenger
{
set { messenger = value; }
}
public static void Show(string message)
{
switch (messenger)
{
case MessengerType.MessageBox:
MessageBox.Show(message);
break;
case MessengerType.Console:
Console.WriteLine(message);
break;
case MessengerType.File:
File.AppendText(message);
break;
}
}
which will lead to a refactor to use polymorphism.
Listing 8 – Using Polymorphism
public interface IMessage
{
void Show(string message);
}
public class MessageBoxMessage : IMessage
{
public void Show(string message)
{
MessageBox.Show(message);
}
}
public class ConsoleMessage : IMessage
{
public void Show(string message)
{
Console.WriteLine(message);
}
}
And the Message class
public class Message
{
private static IMessage messenger = new MessageBoxMessage();
public static IMessage Messenger
{
set { messenger = value; }
}
public static void Show(string message)
{
messenger.Show(“A Name must be entered”);
}
}
Take a look at the code. We have reached the Dependency Injection pattern. Here is how we inject the correct messenger.
Message.Messenger = new ConsoleMessage();
At this point all our tests still pass without any change
Conclusion
We have seen that using TDD and TypeMock, it is possible to build software that can handle change in an incremental manner. When a business need requires the Dependency Injection Pattern, refactor-ing the code will lead to the correct solution, without needing to design it up front. The tests won’t need to be rewritten and we follow the YAGNI principle.
*How do I manage to mock Console.WriteLine in mscorlib?
Handling Support in Agile Teams
As Developer Testing is become mainstream and teams are looking for pragmatic solutions, we are seeing more and more Customers using TypeMock.
Support has always been a top priority here in TypeMock, our mission is to help developers write unit tests, so if they are stuck -we want to help. This has lead to some problems when planning our iterations.
Here are the reasons.
- We don’t know how long we need to spend on support issues. This depends on the number of support issues submitted and their difficulty
- We need to answer the issues in a timely manner
- Support is an interaction task and requires a conversation with the customer, so sometimes issues are waiting for feedback.
- Our customers are developers, and require developers to answer them (for technical issues)
We have thought of a few ways and tried a few.
- Having a dedicated support group.
We haven’t tried this, but a dedicated support group would mean that the support developers will burnout quickly and knowledge transfer could be a problem. We would loses the group responsibility that is a major value in agile teams. When a developer has to deal with the bug he creates directly from the customer, it changes the whole perspective of code quality - Create an iteration and when a support issue arrives – it gets top priority.
This way we get to do the high priority work in any case. This didn’t work very well, there is too much context switching that drives the team crazy. We have seen that this method creates a large risk that the whole iteration in spent in support - Spend the first week of the iteration doing support.
This doesn’t work well as issues that come after this week must wait a few weeks until being looked at and that high priority issues will in any case take preference over development and causes the iteration to grind to a halt. - Have the developers take turns in being dedicated to support, example, have each developer pre-allocated for support one week per month. This gives a good way to measure the amount of support and allows other developers to develop the tasks of the iteration. We are still fine tuning the way that issues get handles from one developer to the next, but it seems to be a good way.
Do you use any other way?
Mocking Extension Methods
With Orcas and TypeMock 4.1 you can now mock Extension methods, easily.
Suppose we added a new method to int that return the Roman Number equivalent of that number:
public static class Extend { public static string RomanNumber(this int number) { // do complex logic return romanString; } }
Now we use this method in our code
string romanNumber = 2010.RomanNumber();
Here is how we mock this.
Reflective Mocks (Community Edition)
We mock that actual static extension method
Mock extentionMethodMock = MockManager.Mock(typeof(Extend)); extentionMethodMock.ExpectAndReturn("RomanNumber","MCMLIX");
Natural Mocks (Professional Edition)
We just call the extension method
using (RecordExpectations rec = new RecordExpectations()) { rec.ExpectAndReturn( 2010.RomanNumber(), "MCMLIX"); }
Checking Arguments
Care should be taken when Checking Arguments as the first argument is the instance of the type we are extending, suppose the extension method takes another argument
public static class Extend { public static string RomanNumber(this int number, bool upperCase) { // do complex logic return romanString; } }
Here is how we validate the arguments.
Reflective Mocks (Community Edition)
We have to implicitly ignore the first argument
// first arg is instance, second must be false Mock extentionMethodMock = MockManager.Mock(typeof(Extend)); extentionMethodMock.ExpectAndReturn("RomanNumber","MCMLIX"). Args(Check.IsAny(),false);
Natural Mocks (Professional Edition)
TypeMock automatically handles the first argument
using (RecordExpectations rec = new RecordExpectations()) { // TypeMock knows that this is an extension method and ignores first
// argument automatically rec.ExpectAndReturn( 2010.RomanNumber(false), "MCMLIX") .CheckArguments(false); }
DotNetRocks Interview
I had a real fun talk with Richard and Carl on DotNetRocks. You can listen to the show here.
The highlight was a grand piano being delivered to Carl during the interview.
Although the show was mainly targeted at Dependency Injections, there are many other design issues that are not required because TypeMock is design agnostic. One is the unnecessary need for virtual method Take a look at Jeremy’s post for more details.
Developers are seeing the value of Unit Testing
This summer has been great for TypeMock. We are showing record growth and have topped our sales and customer base. This is a sign that development groups are seeing the value of unit testing and understanding the need to isolate parts of the code to enable unit testing.
This has of course kept us all very busy.
We are also going to release new features that support .NET 3.5. There are many feature that need to be implemented, mainly support for:
- Extension methods
- Initializers
- Anonymous Types
- Linq
I will talk about these in another post. We are also going to release an Integration API to ease integrating TypeMock with other developer tools.
Dependency Injection – Keep your privates to yourself
Jacob Proffitt has hit the nail on the head with his “I do wish that people would admit that DI doesn’t have compelling applicability outside of Unit Testing” post, the discussion continues with Nate Kohari response post and Jacobs counter post. Oren has also joined in with two posts.
Here a some ideas for you to think about.
DI as a Silver Bullet – You lose power
When you use DI as a ’Silver Bullet’ you are losing more then half the abilities of your programming language. You can not use static methods or the ‘new‘ keyword or sealed types. Oh, you have to make all your methods virtual too. This is going to be even harder once Extension Methods (and Linq) become main stream.
Code to Enable Change – Costs More
Creating Code that is there only to “Enable Change” has a big “YAGNI” written all over it. (Making the code more complex and thus wasting time in development and then in maintenance, for a chance that it will be used in the future). We have understood that this is the wrong plan ages ago. We now know that we can not predict the future and it is best to change our code only when we need to (a process called refactoring).
Keep your Privates to Yourself
Jacob, you are quite right about DI coming into fashion only because the tools where not good enough. DI does have other applications outside testing, but it is being overused in most application only to make the code testable.
One of the first issues that was discussed when TDD was starting was: “should we change our code to make it testable?”
Should we change the visibility of our code?
Should we change the design of our code?
This lead to a collision between testable code and OO encapsulation. Developers started to expose private parts of the code to enable testing. It started with private fields and methods and now it is the complete design. This collision still exists when using inadequate tools, but with the right tools, you can enjoy the best of both worlds.
Get the Best Tools to get the Job Done
Thousands of developers have understood this and have started testing there code without being forced to use a specific pattern required by some tools. Many development shops, didn’t test their code because of the testability/design collision. With the right tools they now understand and test their code.
As Joel Says: “Get the best tools“
A New Trick
I have read this post Interaction based testing using TypeMock.
This code:
Mock clientMock = MockManager.Mock(typeof (Client)); clientMock.Strict = true; Client client = new Client();
Is exactly the same as this code:
MockObject<Client> clientMock = MockManager.MockObject<Client>(); Client client = clientMock.Object;
I prefer the latter, the main reason being that using MockObject ensures that the Object is the one being mocked.
Here is an example that won’t work because we added a new Mock before the previous code:
Mock firstClientMock = MockManager.Mock(typeof (Client)); Mock clientMock = MockManager.Mock(typeof (Client)); clientMock.Strict = true; Client client = new Client(); // this will be contolled by firstClientMock
In this case our client is controlled by the firstClientMock instead of the clientMock. This won’t happen if we use MockObject
Good Programming is about Balance
This post hits the nail on its head:
When good programming practices are just too good.
What struck me … is the ridiculous amount of code required to implement simple things.
I love this paragraph
We all love rules – with them, you don’t have to think much, you just apply what the smart guys think is the best. However, lately we younger generation begin rebel and declare these rules as “elitist crap”.
Good programming is an art, and thus good programmers question and think about all aspects of their code. We don’t just follow rules, we invent them.
Design vs. Process
Oren Eini has posted Tools vs. Design about the Really Simple Dialog post.
It is NOT the design that will give you the freedom to expand and build extendable and maintainable systems. It is impossible to see the future and to implement the best design, that is what YAGNI is about. It is the process that will allow us to meet future requirements. A process that will allow us to change the design as the features grow.
Lets recall the TDD process:
Write Tests -> Code -> Refactor (Design)
Notice that the Design stage is the LAST stage, it is not:
Design (For Testability) -> Test -> Code
Of course we need Tools to support this process, the tools are a testing framework, continuous integration server, and perhaps a mocking framework to allow testing your code no matter what design you chose. We might end up with the same design that Jeremy started with, but we might not. The code might be simple enough to just be there, saving time maintaining the complex MVP code, that many developers are still learning. We do have the option to change this in the future if our code is becoming complex enough to require this.
Using this process we can give our customers business value and shorten the Time To Market, while leaving the option of growth when needed.
I will conclude, a good process is critical to building maintainable, customer value systems, on the other hand shouting out OO Principles will not ensure this
Recent Posts
- Top 5 questions to ask when checking references
- Unacceptable: Unit testing will take 20 years to catch on
- The 4 reasons why we DIDN’T choose Oslo
- Typemock Academy Launch
- The First Rule to Software Craftsmanship
Categories
- .NET Tests
- Agile
- Code Integrity
- Community
- Debugging
- Fun
- Management for Geeks
- Marketing
- Product
- Release
- Reviews
- SharePoint
- TDD
- Time Management
- Uncategorized
- Unit Tests
Archives
- August 2010
- May 2010
- April 2010
- March 2010
- February 2010
- December 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- December 2008
- November 2008
- August 2008
- July 2008
- May 2008
- April 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
