Mocking Test Driven Development - Part 2

Alright, so when I left off last week, we had a EmployeeLogin method that we wrote some tests for to do some parameter checking. Now the fun stuff, Mocking.

We’re going to write a test for the condition that our EmployeeProvider returns “false”, indicating we have an unsuccessful login attempt. Here we go.

1
2
3
4
5
6
7
8
9
[Test(Description="If login provider returns false, return false")]
public void LoginProviderReturnsFalse()
{
    Mockery mocks = new Mockery();
    IEmployeeProvider provider = mocks.NewMock(typeof(IEmployeeProvider))
      as IEmployeeProvider;
    EmployeeModel model = new EmployeeModel(provider);
    model.Login("badusername", "badpassword");
}

There’s that mock object again, remember our constructor requires us to pass it in. The IEmployeeProvider interface represents our Data Source, be it a MSSQL db, web service, or XML file. Because we’re not testing the data source, but rather the EmployeeModel, we want to simulate responses from the data source instead of using an actual one. Here’s where the mocking comes in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Test(Description="If login provider returns false, return false")]
public void LoginProviderReturnsFalse()
{
    Mockery mocks = new Mockery();
    IEmployeeProvider provider = mocks.NewMock(typeof(IEmployeeProvider))
      as IEmployeeProvider;
    Expect.Once.On(provider)
        .Method("LogInEmployee")
        .With("badusername", "badpassword")
        .Will(Return.Value(false));
    EmployeeModel model = new EmployeeModel(provider);
    Assert.IsFalse(model.Login("badusername", "badpassword"));

    mocks.VerifyAllExpectationsHaveBeenMet();
}

So we add an “expectation” for our IEmployeeProvider interface. It’s pretty straightforward, but we’re telling our Mock package that we expect our model to call “LogInEmployee” exactly once (there’s other options such as “Never”, “AtLeastOnce”, “Between”, etc.), passing in “badusername” and “badpassword”, and the Mock of IEmployeeProvider should return the value “false”. We also added two more changes: Assert that the returned value from model.Login is false, as well as asking the mock collection to ensure all the expectations we’ve established have been met. Running this new test in nUnit should come up with an error, which is good because we haven’t actually coded it yet.

1
2
3
4
5
6
7
8
9
//in EmployeeModel
public bool Login(string username, string password)
{
    if(string.isNullOrEmpty(username))
        throw new ArgumentNullException("Username must have a value");
    //remember _employeeProvider is just a private reference to our 
  //Provider passed in the constructor
    return _employeeProvider.LogInEmployee(username, password);
}

Running the test now should work, because we meet the requirements – we’re calling LogInEmployee, and returning the result of the provider call (which happens to be false because we told it to be). Now, there’s a complete example of how you can use Mocks to test independent units of your code without having to rely on setting up DBs or anything else. Not saying we shouldn’t be doing that as well, but that’s what’s known as a Partial System Test and probably more along QA’s or a team lead’s job, possibly as part of a code review or even during the planning phase of the sprint (see: Acceptance Testing, or Behaviour Driven Development)

Something else worth mentioning, if you write a lot of these tests you’ll notice you’re doing the exact same initial 3 or 4 lines of code for setting up the mocks and interfaces. Using nUnit, you can define SetUp and TearDown methods, which execute at the start and end of every test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private Mockery mocks;
private IEmployeeProvider provider;
 
[SetUp]
public void SetUp()
{
    mocks = new Mockery();
    provider = mocks.NewMock(typeof(IEmployeeProvider)
      as IEmployeeProvider;
}
 
[TearDown]
public void TearDown()
{
    mocks.VerifyAllExpectationsHaveBeenMet();
}

Comments