Debugging Mocked Methods
Although strict XP practices, value tests more then debugging, there are many cases where you still have to debug the code base to find defects. Doing this with mocked objects can be very fishy.
Evaluating Mocked Properties
When evaluating methods and Properties in the Debugger, the Debugger Hi-Jacks the running application to run the code that evaluate the values. A mocking framework doesn’t know that you are running in the debugger and will return the mocked value. This might cause the test to fail, because of unexpected calls or different return values.
Breaking While Recording
When in Natural Mocks recording block, breaking inside the block will lead to very strange results. This is because the Hi-Jacked threads that are evaluating Properties are being recorded and mocked. The current workaround is to turn off automatic property evaluation.
Debugging Mocked Methods
When stepping into a mocked method, or putting a break point on it, you will never reach the break point. This is because the method is mocked and is never actually run. This is very confusing and I have heard some developers spending a lot of time trying to understand what is happening.
Preview
These issues have been a major feature of our coming TypeMock version and will all be solved.
- Mocked Property and Method Evaluation will not change the test!
- Breaking in the Recording Block will nor mess up the recording!
- There is a visual cue that will allow you to see that the method is mocked.
Example of debugging a mocked method.
As you can see, it is very easy to see that the method is mocked and understand why you cannot step into the method.
What do you think of the visual cue?
We are thinking about adding more information to the editor
- Return Values
- Conditional Returns (based on arguments)
- Different instances
What other information would you like to know while debugging?
Welcome Ron Shoshani
I would like to welcome Ron Shoshani to our Team.
TypeMock is having a great year and we are growing, Ron will head the Marketing activities in TypeMock and will help introduce tools and techniques to developers around the world, enabling them and their teams to create quality software at speed times.
Welcome Ron!
TypeMock Facebook
TypeMock now has a facebook page. The industry leaders are already there. Don’t miss the party.
Click here to join the typemock group
or the typemock page.
TypeMock and Visual Studio 2008
Although we have supported visual studio 2008 since the Beta version I still think that it important to know that TypeMock supports visual studio 2008.
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?
Recent Posts
- Product Status Peek – 2011
- Thanks Roy
- Typemock starts 2011 in a new location
- Agile Demos Smells
- I want loud disputes in our meetings
Categories
- .NET Tests
- Agile
- Code Integrity
- Community
- Debugging
- Fun
- Management for Geeks
- Marketing
- Product
- Release
- Reviews
- SharePoint
- TDD
- Time Management
- Uncategorized
- Unit Tests
Archives
- January 2011
- December 2010
- October 2010
- 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
