使用Microsoft Fakes进行模拟

时间:2013-06-20 23:29:50

标签: c# .net async-await microsoft-fakes

我使用需要模拟的异步(.net 4.5)方法密封了类。我正在使用Microsoft Fakes,所以他们将“垫片”。以下代码是我需要做的一个例子。它构建但运行时,调用“Login”控制器方法中的“LoginAsync”方法,测试挂起。

  [TestMethod]
  public async Task LoginPost_Returns() {

     using (ShimsContext.Create()) {
        var c = new TestController();
        var user=new User();

        Fakes.ShimUserManager.AllInstances.LoginAsyncString = (um, u) => new Task<IUser>(() => { return user; });

        //call controller method  
        var result = await c.Login(model, returnUrl) as ViewResult;
        var expectedViewName = "Index";
        Assert.IsNotNull(result);
        Assert.AreEqual(expectedViewName, result.ViewName);
     }

//Controller method
public async Task<ActionResult> Login(LoginModel model, string returnUrl) {
     var user = await UserManager.LoginAsync(model.UserName, model.password);
     return View();
}

2 个答案:

答案 0 :(得分:9)

请勿在{{1​​}}代码中使用Task构造函数。如果您只需要一个包含返回值的已完成async,请使用Task

Task.FromResult

作为补充提示,在单元测试中涵盖这些情况是个好主意:

  • 同步成功(IUser user = new User(); Fakes.ShimUserManager.AllInstances.LoginAsyncString = (um, u) => Task.FromResult(user); )。
  • 异步成功(Task.FromResult(user))。
  • 异步错误(Task.Run(() => user))。

答案 1 :(得分:3)

Fakes.ShimUserManager.AllInstances.LoginAsyncString =
    (um, u) => new Task<IUser>(() => { return user; });

这会创建一个未启动的Task。您的代码会挂起,因为Task永远不会启动。要解决这个问题,您可以:

  1. 使用Task.Run()(或Task.Factory.StartNew()),它会返回已经开始的Task
  2. 使用Task.FromResult()。返回已完成的Task
  3. 制作lambda async

    Fakes.ShimUserManager.AllInstances.LoginAsyncString = async (um, u) => user;