Reputation: 803
I have been tasked with building unit tests for a bunch of legacy code. The specific task/goal for the below method is to test that the messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact)
method is being called. I am also posting the test stub I have written so far but I would appreciate some direction because I think I am going down a rabbit hole here. How can I fill in the blanks on my test?
Method being tested:
private void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
if (currentPhoneContact != null)
{
RefreshRenewalActivity();
if (currentPhoneContact.TypeId == ResultType.TookAppointment)
}
NotifyServerOfActivity();
ApplyAppointmentFilters();
this.Activate();
var messageProcessor = new MessageProcessor();
messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact);
}
Test:
[TestFixture, RequiresSTA]
class BucketBrowserTest
{
[Test]
public void logPhoneCallDialog_SaveContact()
{
//Arrange
//Act
//Assert
}
}
Method that calls above method
private void ShowPhoneCallLoggerDialog()
{
PhoneCallLoggerDialog dialog = new PhoneCallLoggerDialog(CurrentCustomer, CurrentBucket.BucketTypeId);
dialog.Owner = this;
dialog.SaveContact += new PhoneCallLoggerDialog.SaveContactHandler(logPhoneCallDialog_SaveContact);
dialog.ShowDialog();
}
Event Handler for calling method
public delegate void SaveContactHandler(PhoneContact currentPhoneContact);
public event SaveContactHandler SaveContact;
Upvotes: 0
Views: 211
Reputation: 14640
Based on the additional information you've supplied, I'm going to outline my assumptions before describing a possible solution:
logPhoneCallDialog_SaveContact()
, won't trigger side effects that prevent it from being testedWhen refactoring legacy code, you often have to make design choices that you would normally avoid. This can include:
public
or internal
In order to get a test around this, you're going to have to do at least one of those things.
Firstly, make logPhoneCallDialog_SaveContact
public
:
public void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
// same body as before
}
Next, extract a method that holds the entire body of the first one, to end up with this:
public void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
SaveContact(currentPhoneContact);
}
private void SaveContact(Contact currentPhoneContact)
{
if (currentPhoneContact != null)
{
RefreshRenewalActivity();
// This code from your example doesn't compile.
if (currentPhoneContact.TypeId == ResultType.TookAppointment)
}
NotifyServerOfActivity();
ApplyAppointmentFilters();
this.Activate();
var messageProcessor = new MessageProcessor();
messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact);
}
Make the new method public
:
public void SaveContact(Contact currentPhoneContact)
{
// same body as before
}
If you haven't already, extract an interface for MessageProcessor
:
public interface IMessageProcessor
{
ProcessCustomerPhoneContactInfo(Contact currentPhoneContact);
}
public class MessageProcessor : IMessageProcessor
{
public void ProcessCustomerPhoneContactInfo(Contact currentPhoneContact)
{
// implementation
}
}
Now modify the methods like so:
public void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
var messageProcessor = new MessageProcessor();
SaveContact(currentPhoneContact, messageProcessor);
}
public void SaveContact(
Contact currentPhoneContact,
IMessageProcessor messageProcessor)
{
if (currentPhoneContact != null)
{
RefreshRenewalActivity();
if (currentPhoneContact.TypeId == ResultType.TookAppointment)
}
NotifyServerOfActivity();
ApplyAppointmentFilters();
this.Activate();
messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact);
}
Now write your unit tests against SaveContact
, mocking IMessageProcessor
, instead of against logPhoneCallDialog_SaveContact
.
Here's an example, as requested. It's been a while since I've used Moq
- which was in your original question - so the syntax may not be quite right, but something like this:
[Test]
public void SavesContact()
{
// Arrange
var contact = new Contact();
var messageProcessor = new Mock<IMessageProcessor>();
var subject = // whatever class contains the logPhoneCallDialog_SaveContact method
// Act
subject.SaveContact(contact, messageProcessor.Object);
// Assert
messageProcessor.Verify(x => x.ProcessCustomerPhoneContactInfo(contact), Times.Once());
}
Also test the case where contact
is null
.
Upvotes: 1
Reputation: 11909
With the code as it stands, you cannot mock out the messageProcessor
, but with a few changes, you could:
IMessageProcessorFactory _messageProcessorFactory;
public TheConstructor(IMessageProcessorFactory processorFactory)
{
_messageProcessorFactory = processorFactory;
}
private void logPhoneCallDialog_SaveContact(Contact currentPhoneContact)
{
if (currentPhoneContact != null)
{
RefreshRenewalActivity();
if (currentPhoneContact.TypeId == ResultType.TookAppointment)
}
NotifyServerOfActivity();
ApplyAppointmentFilters();
this.Activate();
var messageProcessor = _messageProcessorFactory.Create();
messageProcessor.ProcessCustomerPhoneContactInfo(currentPhoneContact);
}
Then you can Moq/Mock the interface and find out if the function was called.
Upvotes: 0