by Patrik Hägne via Legend and truth on 5/15/2010 12:59:00 PM
This is the first part in a series of blog posts that will demo FakeItEasy through TDD-ing a simple Login Service using C#.
This is a port of Brett Schucherts excelent demo of Mockito in Java. As this is a demo of FakeItEasy, I will omit the refactoring part of Brett’s original example, please don’t miss it though as it can be found here. I’ve tried to stay as close to the original example as possible so that they can be easily compared.
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.
What follows is a series of tests to get enough production code written to suggest a better implementation. The first purpose of this tutorial is to demonstrate using FakeItEasy for all types other than the underling LoginService. This is close to a classic mockist approach, though it varies in that I'm emphasizing testing interaction rather than state and deliberately trying to write stable tests that do not depend too much on the underling implementation. In support of this:
When a user logs in successfully with a valid account id and password, the account’s state is set to logged in.
namespace FakeItEasy.LoginService.Tests { using FakeItEasy.Examples.LoginService; using NUnit.Framework; [TestFixture] public class LoginServiceTests { [Test] public void Should_set_account_to_logged_in_when_password_matches() { // Arrange var account = A.Fake<IAccount>(); A.CallTo(() => account.PasswordMatches(A<string>.Ignored)).Returns(true); var accountRepository = A.Fake<IAccountRepository>(); A.CallTo(() => accountRepository.Find(A<string>.Ignored)).Returns(account); var service = new LoginService(accountRepository); // Act service.Login("username", "password"); // Assert A.CallTo(() => account.SetLoggedIn(true)).MustHaveHappened(); } } }
To get this test to compile (but not yet pass), I had to create a few interfaces and add some methods to them. I also had to create a LoginService class:
namespace FakeItEasy.Examples.LoginService { public interface IAccount { bool PasswordMatches(string password); void SetLoggedIn(bool isLoggedIn); } }
namespace FakeItEasy.Examples.LoginService { public interface IAccountRepository { IAccount Find(string username); } }
namespace FakeItEasy.Examples.LoginService { using System; public class LoginService { public void Login(string username, string password) { } } }
Creating the test and adding all of theses classes gets my first test to Red with the following error:
Assertion failed for the following call: 'FakeItEasy.Examples.LoginService.IAccount.SetLoggedIn(True)' Expected to find it once but no calls were made to the fake object.
The test as written requires that the production code (LoginService) sends a message to a particular IAccount object. The LoginService retrieves accounts via its IAccountRepository, which it received during construction. So all we need to do is remember that particular IAccountRepository object and use it:
namespace FakeItEasy.Examples.LoginService { using System; public class LoginService { private IAccountRepository accountRepository; public LoginService(IAccountRepository accountRepository) { this.accountRepository = accountRepository; } public void Login(string username, string password) { var account = this.accountRepository.Find(username); account.SetLoggedIn(true); } } }
There we have it, our first test case implemented, in the next part we’ll create another test.
Original Post: FakeItEasy Login Service Example Series – Part 1
The content of the postings is owned by the respective author. CSharpFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on CSharpFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.