Monday, May 14, 2012

Moq, TDD and multiple layers

I have a data assembly which defines my repositories.



I then have a service assembly which defines my services, each service has a repository injected into the constructor by Ninject.



When I'm unit testing my service methods, everything is fine:



[TestClass]
public class UserTests
{
IQueryable<User> users;
int userID;

public UserTests()
{
users = new List<User>()
{
new User { EmailAddress = "known@user.com", Password = "password", ID = 1}
}.AsQueryable();
}

[TestMethod]
public void Known_User_Can_Login()
{
// Arrange
var repository = new Mock<IUserRepository>();
var service = new UserService(repository.Object);

repository.Setup(r => r.GetAll())
.Returns(users);

// Act
bool loggedIn = service.UserLogin("known@user.com", "password", out userID);

// Assert
Assert.IsTrue(loggedIn);
Assert.AreEqual(1, userID);
}

[TestMethod]
public void Unknown_User_Cannot_Login()
{
// Arrange
var repository = new Mock<IUserRepository>();
var service = new UserService(repository.Object);

repository.Setup(r => r.GetAll())
.Returns(users);

// Act
bool loggedIn = service.UserLogin("unknown@user.com", "password", out userID);

//
Assert.IsFalse(loggedIn);
}
}


However, I'm running into problems when testing my controller (another level down).



My controller has dependencies on a service, and the service depends on a repository. I can't seem to get my controller tests to work. Here's what I have so far:



 [TestClass]
public class AccountTests
{
IQueryable<User> users;

public AccountTests()
{
users = new List<User>()
{
new User { CompanyId = 1, EmailAddress = "known@user.com", Password = "password"},
new User { CompanyId = 1, EmailAddress = "unknown@user.com", Password = "password"}
}.AsQueryable();
}

[TestMethod]
public void Known_User_Can_Login()
{
int userID = 0;

var repo = new Mock<IUserRepository>();

// Arrange
var service = new Mock<UserService>(repo);
var controller = new AccountController(service.Object);

// Act
var result = controller.Login(new LoginModel { EmailAddress = "known@user.com", Password = "password" }) as RedirectToRouteResult;

// Assert
service.Verify(x => x.UserLogin("known@user.com", "password", out userID), Times.Once());
Assert.AreEqual("Index", result.RouteValues["Action"]);
}
}


I keep getting an error about instantiating the UserService (i'm attempting to pass an instance of the UserRepository to it but it isn't working).



I must be doing something daft, but what?





No comments:

Post a Comment