I have been working on some acceptance tests and found a valuable tool — SpecFlow. Nowadays, testing with SpecFlow/Cucumber or similar tools seems to gain speed, with more and more people consider utilising power of ATDD and BDD. Essentially, SpecFlow makes it possible for business people to define valuable behaviour for the project.
I have adapted code defined in Oren’s blog to show the simplicity of SF. In the post Oren presented new syntax for unit testing namely Arrange-Act-Assert. The types under test are defined as
public interface IUserRepository
{
User GetUserById(int id);
}
public interface INotificationSender
{
void Send(string message);
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class LoginController
{
private readonly IUserRepository repository;
private readonly INotificationSender sender;
public LoginController(IUserRepository repository, INotificationSender sender)
{
this.repository = repository;
this.sender = sender;
}
public void ForgotMyPassword(int userId)
{
User user = repository.GetUserById(userId);
sender.Send("Changed password for " + user.Name);
}
}
And the test looks like this:
[Test]
public void WhenUserForgetPasswordWillSendNotification_UsingExpect()
{
var userRepository = MockRepository
.GenerateStub<IUserRepository>();
var notificationSender = MockRepository
.GenerateMock<INotificationSender>();
userRepository.Stub(x => x.GetUserById(5))
.Return(new User { Id = 5, Name = "ayende" });
notificationSender.Expect(x => x.Send(null))
.Constraints(Text.StartsWith("Changed"));
new LoginController(userRepository, notificationSender)
.ForgotMyPassword(5);
notificationSender.VerifyAllExpectations();
}
Well, if I didn’t happen to know the programming language, I would immediately fail to understand what is happening. Let’s see how I can rewrite the test in a more domain-oriented and business-friendly way.
Firstly, using NuGet I install the following tools
PM> install-package SpecFlow
PM> install-package RhinoMocks
Secondly, I define a test from a business perspective. Tests are written in a Gherkin language.
Feature: Send Notification
In order to automate support services
And solve trivial problems quickly
As a company with high standard of support
We want to send emails
@sendNotification
Scenario: Send forgot password notification
Given user forgot password
When he clicks on a forgot password link
Then new password is sent
Now, as a developer I generate a “code behind” and insert it into the send notification feature steps
[Binding]
public class SendNotificationSteps
{
private IUserRepository userRepository;
private INotificationSender notificationSender;
[BeforeScenario]
public void Initialize()
{
userRepository = MockRepository.GenerateStub<IUserRepository>();
notificationSender = MockRepository.GenerateMock<INotificationSender>();
}
[Given(@"user forgot password")]
public void GivenUserForgotPassword()
{
userRepository.Stub(x => x.GetUserById(5))
.Return(new User { Id = 5, Name = "ayende" });
notificationSender.Expect(x => x.Send(null))
.Constraints(Text.StartsWith("Changed"));
}
[When(@"he clicked on a forgot password link")]
public void WhenHeClickedOnAForgotPasswordLink()
{
new LoginController(userRepository, notificationSender).ForgotMyPassword(5);
}
[Then(@"password changed notification is sent")]
public void ThenPasswordChangedNotificationIsSent()
{
notificationSender.VerifyAllExpectations();
}
}
So without altering Oren’s test (just rearranging), this is what I can get as the output

Conclussions:
SpecFlow allows non-technical folks to define features and correspondent tests. Each line of scenario corresponds to a method, where a technical dude writes code. Features are defined in a meta language Gherkin that can be learned within five minutes. SpecFlow supports NUnit, MSTest, MbUnit and any mocking framework. What I noticed so far it is a little bit tedious to configure tests on a build machine and as it is a fresh tool occasional error do occur (however they are not brain teasers and can be quickly fixed).
If you enjoyed this post, make sure you subscribe to my RSS feed!
f3536c49-5625-48b2-a926-6034d6bdb350|0|.0
I got an interesting question today and I partly failed to answer it.
The question was: what is the difference between a mock and a stub?
Although I spent sufficient amount of time writing unit tests with and without mocking objects, I was unable to provide a clear answer. Having searched the internet afterwards, I found one of the classic article by M. Fowler that I managed to miss somehow. The article is very detailed, but long story told short:
Using stubs – is the classic TDD approach where unit tests are designed to check state. A general core workflow would be calling a method of an object/type with subsequent verification that the state has been updated.
Using mocks – is a TDD variation - BDD - that aims to track behaviour. Typical scenario would be creating a pre-programmed workflow and check if a real-world object follows the predefined behaviour.
What is better? Which path to choose? These are debatable questions and are highlighted by Martin in his article “Mocks Aren't Stubs”.
If you enjoyed this post, make sure you subscribe to my RSS feed!
5e5ee717-141d-4017-9fec-2ec31d19e4e8|0|.0