I'm still in the process of learning the how, when and wheres of Rhino Mocks. I just finished watching this tutorial: http://dimecasts.net/Content/WatchEpisode/12, I even typed it out using 3.5+ AAA syntax from Record/Playback but my question is how is this useful what can you do w/ this. I'm fundamentally missing something.
public class EmailerService
{
public bool SendEmail(string email, string message)
{
return false;
}
}
public class Emailer
{
private IEmailerService _emailerService;
public Emailer(IEmailerService emailerService)
{
this._emailerService = emailerService;
}
public void SendBatchEmails()
{
var emails = new Dictionary<string, string>
{
{"fred1@foo.com", "Hello1"},
{"fred2@foo.com", "Hello2"},
{"fred3@foo.com", "Hello3"},
{"fred4@foo.com", "Hello4"}
};
foreach(KeyValuePair<string, string> email in emails)
{
if(!_emailerService.SendEmail(email.Key, email.Value))
{
throw new Exception(" You've Err'd");
}
}
}
}
My Test are as follows:
[TestMethod]
public void EmailerServiceTest()
{
//Arrange
var emailerServie = MockRepository.GenerateMock<IEmailerService>();
emailerServie.Expect(x => x.SendEmail("", "")).IgnoreArguments().Return(true).Repeat.Any();
//Act
var emailer = new Emailer(emailerServie);
emailer.SendBatchEmails();
}
[TestMethod]
public void EmailerServiceTestException()
{
//Arrange
var emailerServie = MockRepository.GenerateMock<IEmailerService>();
emailerServie.Expect(x => x.SendEmail("", "")).IgnoreArguments().Throw(new Exception("You've Err'd"));
//Act
var emailer = new Emailer(emailerServie);
emailer.SendBatchEmails();
}
If you know when and where it will fail whats the point of writing a test where you already know the answer? Thanks
Your tests so far look like you are on the right path. If your tests seem obvious, that is a good thing. They are there to ensure expected behavior. If months from now you have forgotten about Emailer
but you change EmailerService
to throw an exception on a failure, instead of return false, your tests will remind you that Emailer
is expecting different behavior and needs to be updated.
When writing unit tests, I always do two things before any implementation: 1) writing a clear test function name, and divide the method into the three components Arrange, Act, Assert. This helps me to keep my expectations of the test clear, and to ensure that I don't forget anything.
It appears as if you have forgotten to include the Assert portion of the test:
[TestMethod]
public void Emailer_IsCalled_SendEmailIsCalled()
{
//Arrange
var emailerService = MockRepository.GenerateMock<IEmailerService>();
emailerServie.Expect(x => x.SendEmail("", "")).IgnoreArguments().Return(true).Repeat.Any();
//Act
var emailer = new Emailer(emailerService);
emailer.SendBatchEmails();
//Assert
emailer.VerifyAllExpectations();
}
In the second test, it seems that you want to test that if SendEmail
fails an exception is thrown. In this case, emailerService
is better suited as a Stub:
[TestMethod, ExpectedException(typeof(Exception))]
public void Emailer_SendEmailReturnsFalse_ThrowException()
{
//Arrange
var emailerService = MockRepository.GenerateStub<IEmailerService>();
emailerServie.Stub(x => x.SendEmail("", "")).IgnoreArguments().Return(false);
//Act
var emailer = new Emailer(emailerService);
emailer.SendBatchEmails();
//Assert
//Expect Exception
/* Even when I don't have and assert call here, I usually leave a note*/
}