2013-03-21 171 views
0

我的测试方法。我正在使用xUnitThreadAborted在Moq.Verify使用异步等待时

[Fact] 
public async void AccountController_RegisterTest() 
{ 
    const string testEmail = "[email protected]"; 
    const string testPassword = "[email protected]"; 

    var cacheMock = new Mock<ICacheProvider>(); 
    var languageResolverMock = new Mock<ILanguageResolver>(); 

    languageResolverMock.Setup(x => x.GetCorrectLanguage("en", "en")).Returns("en"); 
    languageResolverMock.Setup(x => x.GetDefaultLanguage()).Returns("en"); 

    var contextMock = new Mock<IContextFactory>(); 
    var localizationProvider = new Mock<ILocalizationProvider>(); 

    localizationProvider.Setup(x => x.GetString(It.IsAny<string>(), It.IsAny<string>())).Returns(String.Empty); 

    var authenticationProvider = new Mock<IAuthenticationProvider>(); 

    authenticationProvider.Setup(x => x.CheckExistsUser(It.IsAny<string>())).Returns(async() => false); 
    authenticationProvider.Setup(x => x.CreateUser(It.IsAny<RegisterModel>())).Returns(async() => true); 

    var languagesRepository = new Mock<LanguagesRepository>(MockBehavior.Default, contextMock.Object, cacheMock.Object); 

    languagesRepository.Setup(x => x.GetCorrectLanguage(It.IsAny<string>())).Returns(() => Task.Factory.StartNew(() => new Language { Code = "EN", Fullname = "English" })); 
    languagesRepository.Setup(x => x.GetDefaultLanguageAsync()).Returns(async() => new Language { Code = "EN", Fullname = "English" }); 
    languagesRepository.Setup(x => x.AvailableLanguagesAsync()).Returns(async() => (new List<Language> { new Language { Code = "EN", Fullname = "English" } }).AsEnumerable()); 

    var controllerMock = new Mock<AccountController>(MockBehavior.Default, authenticationProvider.Object, languagesRepository.Object, localizationProvider.Object, languageResolverMock.Object, cacheMock.Object) { CallBase = true }; 

    controllerMock.Setup(x => x.CurrentAvailableLanguages()).Returns(() => Task.Factory.StartNew(() => (new List<SelectListItem> { new SelectListItem { Text = "English", Value = "En" } }).AsEnumerable())); 
    controllerMock.Setup(x => x.InitAvailableLanguages()); 
    controllerMock.Setup(x => x.SetAuthenticateCookie(It.IsAny<RegisterModel>())); 
    controllerMock.Setup(x => x.RedirectToHomePage()).Returns(() => Task.Factory.StartNew(() => new RedirectToRouteResult(new RouteValueDictionary()))); 

    await controllerMock.Object.Register(new RegisterModel { Email = testEmail, LanguageID = 0, Password = testPassword, RememberMe = true }); 

    authenticationProvider.Verify(x => x.CheckExistsUser(It.Is<string>(y => y == testEmail)), Times.Once()); 
    authenticationProvider.Verify(x => x.CreateUser(It.Is<RegisterModel>(y => y.Email == testEmail && y.Password == testPassword)), Times.Exactly(12)); 
} 

此行总是抛出ThreadAborted异常。

authenticationProvider.Verify(x => x.CheckExistsUser(It.Is<string>(y => y == testEmail)), Times.Once()); 

但是,当我调试测试 - 它会正常运行。我是线程不完全返回结果,,但我使用等待!

[AllowAnonymous] 
[HttpPost] 
public async Task<ActionResult> Register(RegisterModel model) 
{ 
    InitAvailableLanguages(); 

    try 
    { 
     ValidationResult result; 
     if ((result = new RegisterModelCustomValidator().Validate(model)).IsValid) 
     { 
      if (!(await this.AuthProvider.CheckExistsUser(model.Email))) 
      { 
       if (!(await this.AuthProvider.CreateUser(model))) 
       { 
        ModelState.AddModelError(string.Empty, L("Server error. Please, try later...")); 
        return View(model); 
       } 

       SetAuthenticateCookie(model); 

       return await RedirectToHomePage(); 
      } 

      ModelState.AddModelError(string.Empty, L("User already exists")); 

      return View(model); 
     } 

     foreach (var error in result.Errors) 
      ModelState.AddModelError(error.PropertyName, this.LocalizationProvider.GetString(error.ErrorMessage, Thread.CurrentThread.CurrentUICulture.Name)); 

    } 
    catch (Exception ex) 
    { 
     Logger.Error(ex); 
    } 

    return View(model); 
} 

输出窗口:

Step into: Stepping over non-user code 'System.Linq.Expressions.Expression.Parameter' 
The thread 'xUnit.net STA Test Execution Thread' (0x2ab8) has exited with code 0 (0x0). 
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in System.Core.dll 
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in Core.Test.dll 
An exception of type 'System.Threading.ThreadAbortException' occurred in Core.Test.dll but was not handled in user code 
Step into: Stepping over non-user code 'System.Threading.ExecutionContext.RunInternal' 
Step into: Stepping over non-user code 'System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run' 
Step into: Stepping over non-user code 'System.Threading.ThreadPoolWorkQueue.Dispatch' 
Step into: Stepping over non-user code 'System.Threading.ThreadPoolWorkQueue.Dispatch' 
The program '[124] JetBrains.ReSharper.TaskRunner.CLR4.MSIL.exe: Managed (v4.0.30319)' has exited with code 0 (0x0). 

回答

2

的xUnit不支持async void单元测试AFAIK。尝试改变你的单元测试返回Task