这是我的代码
public interface IUserManager
{
Task<int> PostUser(User user);
IQueryable<User> GetUserById(long userId);
}
public class UserManager : IUserManager
{
public UserManager(DataContext context)
{
this.DataContext = context;
}
public async Task<int> PostUser(User user)
{
this.DataContext.User.Add(user);
return await this.DataContext.SaveChangesAsync().ConfigureAwait(false);
}
public IQueryable<User> GetUserById(long userId)
{
return this.DataContext.User
.Where(userNotes => userNotes.UserId == userId).AsQueryable();
}
}
控制器:
public class UserController : BaseController
{
private readonly IUserManager userManager;
public UserController()
{
this.userManager = new UserManager();
}
public UserController(IUserManager userManager)
{
this.userManager = userManager;
}
[EnableQuery]
public IQueryable<User> Get([FromODataUri]long userId)
{
return this.userManager.GetUserById(userId);
}
public HttpResponseMessage Post(User user)
{
if (userNote == null || !ModelState.IsValid)
{
return this.BuildErrorResponse(ResponseCodes.INVALID_MISSING_INPUTS);
}
if (this.userManager.PostUser(user).Result <= 0)
{
return this.BuildErrorResponse(ResponseCodes.USER_ADD_FAILED);
}
return this.BuildSuccessResponse<User>(ResponseCodes.USER_ADDED, user);
}
}
Moq测试:
[TestClass]
public class UnitTest
{
IUserManager userManagerMock;
Mock<IUserManager> iUserManagerMock;
[TestInitialize]
public void Setup()
{
//.. setup variables and mock data
userManagerMock = new UserManager(ContextMock.Object);
iUserManagerMock.Setup(u => u.PostUser(It.IsAny<User>()))
.ReturnsAsync(1);
}
[TestMethod]
public void Post()
{
var controller = new UserController(userManagerMock); //userNotesManagerMock will have the mock data //and mock methods setup
var httpResponse = controller.Post(userPostMock); //userPostMock will have mock data to save
//Assert.AreEqual(HttpResponseMessage, result);
}
}
我在这里看到了一个帖子方法。我也有一个Get方法,它与模拟数据完美配合。
但是当我通过Post调试时,以下语句的数据总是返回ZERO而不是1,这是我在ReturnsAsync中设置的。
this.userManager.PostUser(user).Result <= 0 //this always gives me zero
帖子有什么问题?我做错了吗?
任何人都可以对此有所了解
修改
以下是Test方法和设置的GET版本
[TestInitialize]
public void Setup()
{
//dummy data setup
UserMock = new List<User>
{
new User { //blah blah properties }
}.AsQueryable();
//context setup
dbSetUserMock = new Mock<IDbSet<User>>();
dbSetUserMock.Setup(m => m.Provider).Returns(UserMock.Provider);
dbSetUserMock.Setup(m => m.Expression).Returns(UserMock.Expression);
dbSetUserMock.Setup(m => m.ElementType).Returns(UserMock.ElementType);
dbSetUserMock.Setup(m => m.GetEnumerator()).Returns(UserMock.GetEnumerator());
UserContextMock = new Mock<DataContext>();
UserContextMock.Setup(s => s.User).Returns(dbSetUserMock.Object);
//inject the context to manager
UserManagerMock = new UserManager(UserContextMock.Object);
iUserManagerMock = new Mock<IUserManager>();
iUserManagerMock.Setup(notes => notes.PostUserNote(It.IsAny<User>()))
.ReturnsAsync(1);
}
[TestMethod]
public void Get_User_Success()
{
var controller = new UserController(UserManagerMock);
var values = controller.Get(100);
Assert.AreEqual(100, values.FirstOrDefault().UserId);
}
Get_User_Success
现在可以很好地使用虚拟数据集,我可以在没有iUserManagerMock
对象的情况下通过测试。原因是我想在Manager类中执行GetUser()
方法内的代码。
我在这里还有另外一个问题。正如我在ReturnAsync for Post操作中将预期结果设置为1。如何为失败案例场景构建测试方法,因为POST方法的返回对于失败案例仍然是1?
答案 0 :(得分:1)
您正在混淆设置。如果测试中的方法是UserController.Post
,并且您想通过UserManager
界面模拟IUserManager
,那么您不需要手动设置新版本。
[TestClass]
public class UnitTest {
[TestMethod]
public void UserController_Should_Post_User_Ok() {
//Arrange
var userPostMock = new User { UserId = 100 };
var userManagerMock = new Mock<IUserManager>();
userManagerMock.Setup(u => u.PostUser(It.IsAny<User>())).ReturnsAsync(1);
var controller = new UserController(userManagerMock.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
//Act
var httpResponse = controller.Post(userPostMock);
//Assert
Assert.AreEqual(System.Net.HttpStatusCode.OK, httpResponse.StatusCode);
}
[TestMethod]
public void UserController_Should_Post_User_Fail() {
//Arrange
var userPostMock = new User { UserId = 100 };
var userManagerMock = new Mock<IUserManager>();
userManagerMock.Setup(u => u.PostUser(It.IsAny<User>())).ReturnsAsync(0);//Replicating a failed post
var controller = new UserController(userManagerMock.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
//Act
var httpResponse = controller.Post(userPostMock);
//Assert
Assert.AreEqual(System.Net.HttpStatusCode.InternalServerError, httpResponse.StatusCode);
}
[TestMethod]
public void UserManager_Should_Get_User_Success() {
//Arrange
var userMock = new List<User>
{
new User (){ UserId=100 }
}.AsQueryable();
//context setup
var dbSetUserMock = new Mock<IDbSet<User>>();
dbSetUserMock.Setup(m => m.Provider).Returns(userMock.Provider);
dbSetUserMock.Setup(m => m.Expression).Returns(userMock.Expression);
dbSetUserMock.Setup(m => m.ElementType).Returns(userMock.ElementType);
dbSetUserMock.Setup(m => m.GetEnumerator()).Returns(userMock.GetEnumerator());
var userContextMock = new Mock<DataContext>();
userContextMock.Setup(s => s.User).Returns(dbSetUserMock.Object);
//inject the context to manager
var userManagerMock = new UserManager(userContextMock.Object);
//Act
var values = userManagerMock.GetUserById(100);
//Assert
Assert.AreEqual(100, values.FirstOrDefault().UserId);
}
}