Asp.net mvc 3 Moq、TDD和多层
我有一个数据集,它定义了我的存储库 然后我有一个定义我的服务的服务程序集,每个服务都有一个存储库,由Ninject注入构造函数 当我对我的服务方法进行单元测试时,一切都很好:Asp.net mvc 3 Moq、TDD和多层,asp.net-mvc-3,tdd,ninject,moq,Asp.net Mvc 3,Tdd,Ninject,Moq,我有一个数据集,它定义了我的存储库 然后我有一个定义我的服务的服务程序集,每个服务都有一个存储库,由Ninject注入构造函数 当我对我的服务方法进行单元测试时,一切都很好: [TestClass] public class UserTests { IQueryable<User> users; int userID; public UserTests() { users = new List<User>()
[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]
公共类用户测试
{
易读用户;
int用户标识;
公共用户测试()
{
用户=新列表()
{
新用户{EmailAddress=”known@user.com,Password=“Password”,ID=1}
}.AsQueryable();
}
[测试方法]
公共无效已知用户可以登录()
{
//安排
var repository=newmock();
var service=newuserservice(repository.Object);
repository.Setup(r=>r.GetAll())
.退货(用户);
//表演
bool loggedIn=service.UserLogin(“known@user.com“,”密码“,输出用户ID);
//断言
Assert.IsTrue(loggedIn);
AreEqual(1,userID);
}
[测试方法]
public void未知\u用户\u无法\u登录()
{
//安排
var repository=newmock();
var service=newuserservice(repository.Object);
repository.Setup(r=>r.GetAll())
.退货(用户);
//表演
bool loggedIn=service.UserLogin(“unknown@user.com“,”密码“,输出用户ID);
//
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"]);
}
}
[TestClass]
公共类会计测试
{
易读用户;
公共会计测试()
{
用户=新列表()
{
新用户{CompanyId=1,电子邮件地址=”known@user.com,Password=“Password”},
新用户{CompanyId=1,电子邮件地址=”unknown@user.com,Password=“Password”}
}.AsQueryable();
}
[测试方法]
公共无效已知用户可以登录()
{
int userID=0;
var repo=new Mock();
//安排
var服务=新的模拟(repo.Object);
var控制器=新的AccountController(service.Object);
//表演
var result=controller.Login(新的LoginModel{EmailAddress=”known@user.com,Password=“Password”})作为重定向路由结果;
//断言
验证(x=>x.UserLogin(“known@user.com“,”password“,out userID),Times.Once());
Assert.AreEqual(“Index”,result.routeValue[“Action”]);
}
}
我在实例化UserService时一直遇到一个错误(我试图将UserRepository的一个实例传递给它,但它不起作用)
我一定在做一些愚蠢的事情,但是什么呢?
UserService
类我猜它不是一个接口或抽象类,如果不是,那么它肯定会失败,因为Mock无法创建UserService
的实现。因此,要么为UserService创建接口,要么将其定义为抽象类,要么按如下方式实例化它:
var service=新用户服务(repo.Object)
或者,您可以使用Mock.Create()
,但您需要使用Mock.Provide()
api提供所有实现用户服务所需
希望这有帮助
如果这不是问题,请使用UserService和存储库的类更新问题确保UserService是一个接口 此外,在第二次测试中,您不能像在此处所做的那样创建IUserRepository的实例:
var repo = new Mock<IUserRepository>();
// Arrange
var service = new Mock<UserService>(repo.Object);
var repo=new Mock();
//安排
var服务=新的模拟(repo.Object);
由于UserService是模拟的,因此它无论如何都不会调用IUserRepository,并且在创建模拟时不必提供它的依赖项
您需要做的只是通过以下方式创建UserService的模拟:
var service = new Mock<UserService>();
var service=newmock();
即使是严格的用户服务通常也依赖于存储库,Moq只会提供对方法的固定响应,因此不需要调用实际的存储库。我不知道Moq/ninject,但我的看法是:既然你在嘲笑你的服务,它就永远不需要存储库。您的实际实现可能会失败。你只需要测试一个级别。你有你的SUT,只需要模拟SUT将要访问的对象。@Paul我想看看你应用程序使用的合成根。