我有一个数据程序集,用于定义我的存储库。
然后我有一个定义我的服务的服务程序集,每个服务都有一个由Ninject注入到构造函数中的存储库。
当我对我的服务方法进行单元测试时,一切都很好:
[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);
}
}
但是,我在测试控制器时遇到了问题(另一个级别下降)。
我的控制器依赖于服务,服务依赖于存储库。我似乎无法让我的控制器测试工作。这是我到目前为止所做的:
[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.Object);
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"]);
}
}
我一直收到有关实例化UserService的错误(我正在尝试将UserRepository的实例传递给它但它无法正常工作)。
我必须做些愚蠢的事,但是什么?
答案 0 :(得分:2)
确保UserService是一个接口。
此外,你必须不在你的第二次测试中创建一个IUserRepository实例:
var repo = new Mock<IUserRepository>();
// Arrange
var service = new Mock<UserService>(repo.Object);
由于UserService被模拟,因此无论如何都不会调用IUserRepository,并且在创建模拟时不必提供它的依赖项。
您需要做的只是以这种方式为UserService创建模拟:
var service = new Mock<UserService>();
即使强硬的UserService通常依赖于存储库,Moq也只会提供对方法的预设响应,因此不需要调用实际的存储库。
答案 1 :(得分:1)
UserService
类我猜不是接口或抽象类,如果没有,那么它必然会失败,因为Mock无法创建UserService
的实现。因此,要么为UserService创建接口,要么将其定义为抽象类,或者按如下方式对其进行实例化:
var service = new UserService(repo.Object);
或者您可以使用Mock.Create<UserService>()
,但您需要使用Mock.Provide<T>()
api提供所有实施UserService。
希望这会有所帮助。
如果这不是问题,请使用UserService和您的存储库的类更新问题