Sunday, May 23, 2010

FakeItEasy Login Service Example Series – Part 3

This is the fourth part in the series of posts where I’m porting Brett Schucherts excelent demo of Mockito in Java to C# and FakeItEasy.

The source for this example series can be found in a Mercurial repository at Google code. Each test implementation and following code update is a separate commit so you can easily update your repository to look at the full code at any given state. Find the repository here.

Part 1 can be found here.

Part 2 can be found here.

Test 3 – Not logging in with wrong password

The first two tests have made good progress, however to keep the number of assertions per test small (so far one) and to make individual tests less dependent on the underlying implementation, this next test forces a fix to the code and probably would have been a better second test than one you just created.

The Test

[Test]
public void Should_not_log_in_when_password_is_wrong()
{
    // Arrange
    A.CallTo(() => this.account.PasswordMatches(A<string>.Ignored)).Returns(false);

    // Act
    this.service.Login("username", "wrong password");

    // Assert
    A.CallTo(() => this.account.SetLoggedIn(true)).MustNotHaveHappened();
}

Test Description

This test takes advantage of the recent test refactoring. Before ever getting into the test method, the SetUp method:

  1. Created a fake IAccount.
  2. Created a fake IAccountRepository.
  3. Configured the IAccountRepository fake to return the fake IAccount for any username.
  4. Created a LoginService and injected the IAccountRepository.

There’s not much left:

  1. Set the fake IAccount to not match any password.
  2. Attempt to login.
  3. Assert that the SetLoggedIn method is never called with true.

Things Created for Compilation

This test did not require any existing classes to have new methods added.

Failing Test

The test fails with this message, FakeItEasy finds the specified method call once and lists all the calls to the faked IAccount.

 Assertion failed for the following call:
    'FakeItEasy.Examples.LoginService.IAccount.SetLoggedIn(True)'
  Expected to find it exactly never but found it #1 times among the calls:
    1.  'FakeItEasy.Examples.LoginService.IAccount.SetLoggedIn(True)'
    2.  'FakeItEasy.Examples.LoginService.IAccount.PasswordMatches("wrong password")'
 

Code Updated to get Test to turn Green

The LoginService needs to be updated:

namespace FakeItEasy.Examples.LoginService
{
    using System;

    public class LoginService
    {
        private IAccountRepository accountRepository;
        private int numberOfFailedAttempts;

        public LoginService(IAccountRepository accountRepository)
        {
            this.accountRepository = accountRepository;
        }

        public void Login(string username, string password)
        {
            var account = this.accountRepository.Find(username);
            
            if (account.PasswordMatches(password))
            {
                account.SetLoggedIn(true);
            }
            else
            {
                this.numberOfFailedAttempts++;
            }

            if (this.numberOfFailedAttempts == 3)
            {
                account.SetRevoked(true);
            }
        }
    }
}

No comments:

Post a Comment