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?
Great Time in Tech Ed Barcelona
We had a great time in Barcelona, The TechEd team has done it again and have created a top-notch conference. Apart from not being able to get tickets to the Barcelona Football match, we practically had everything made out for us.
We had some really good talks and met up with great people from the industry. Thank you all.
TypeMock is a Silver Bullet
During the TechEd in Bacelona, I overheard developers talking about TDD and Mocking. Then I heard one of them say that TypeMock is a Silver Bullet, it can just help you solve all your mocking problems. I love that, thanks guys.
Roys Test Name Convention
I just loved the way Roy explained how developers normally name their tests without really thinking about them. for example SumNegitiveNumber5 (yup, I have been down that road before) and his naming convention really make sense.
But what I really liked was the template he wrote and how the Tab key browses through the three the different parts of the name.
Rollback for database testing
Roy Osherove had a good speak in TechEd Barcelona 2007, about using the roll back attribute for database testing, and it works really well, keeping the test case isolated. Except in cases where the production code ignores transactions that are higher up in the hierarchy. This will happen if the TransactionOption is RequiresNew
Roy suggested to always use: Supported, but we believe that there should be a way to test you code even if you require and need to use another transactions.
So here is how I would do it with TypeMock.
I would create a new attribute for the rollback and make sure that all future TransactionOptions are Mocked.
This way our test will look like:
[TestMethod,Rollback,VerifyMocks]
public void MyDatabaseTest()
{
}
Here is the code, to enable this (for any test framework) simple add the attribute.
[AttributeUsage(AttributeTargets.Method)]
public sealed class RollBackAttribute : DecoratorAttribute
{
public override object Execute()
{
// Start transaction
ServiceConfig config = new ServiceConfig();
config.Transaction = TransactionOption.RequiresNew;
ServiceDomain.Enter(config);
// make sure that all future Transactions rely on this transaction by mocking all sets to the Transaction
Mock serviceConfigMock = MockManager.MockAll<ServiceConfig>(Constructor.NotMocked);
serviceConfigMock.ExpectSetAlways("Transaction");
try
{
// run our tests
return base.CallDecoratedMethod();
} finally
{
// clear unused mocks
serviceConfigMock.Clear();
// rollback database
if(ContextUtil.IsInTransaction)
{
ContextUtil.SetAbort();
}
ServiceDomain.Leave();
}
}
}









