質問

I have sealed classes with async(.net 4.5) methods that need to be mocked. I'm using Microsoft Fakes and so they will be "shims". The following code is an example of what I need to do. It builds but when run and the "LoginAsync" method within the "Login" controller method is called, the test hangs.

  [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();
}
役に立ちましたか?

解決

Don't use the Task constructor in async code. If you just need a completed Task with a return value, use Task.FromResult:

IUser user = new User();
Fakes.ShimUserManager.AllInstances.LoginAsyncString = (um, u) => Task.FromResult(user);

As an additional tip, it's a good idea to cover these cases in your unit tests:

  • Synchronous success (Task.FromResult(user)).
  • Asynchronous success (Task.Run(() => user)).
  • Asynchronous error (Task.Run(() => { throw new InvalidOperationException("or whatever"); return user; })).

他のヒント

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

This creates an unstarted Task. Your code hangs, because the Task is never started. To fix that, you can:

  1. Use Task.Run() (or Task.Factory.StartNew()), which returns an already started Task.
  2. Use Task.FromResult(). which returns an already completed Task.
  3. Make the lambda async:

    Fakes.ShimUserManager.AllInstances.LoginAsyncString = async (um, u) => user;
    
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top