Moq中的ReturnsAsync不起作用

时间:2016-04-21 10:07:30

标签: asp.net-mvc asp.net-web-api asp.net-web-api2 moq

这是我的代码

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?

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);
    }
}