我使用需要模拟的异步(.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();
}
答案 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
永远不会启动。要解决这个问题,您可以:
Task.Run()
(或Task.Factory.StartNew()
),它会返回已经开始的Task
。Task.FromResult()
。返回已完成的Task
。制作lambda async
:
Fakes.ShimUserManager.AllInstances.LoginAsyncString = async (um, u) => user;