繁体   English   中英

使用async-await时,Moq.Verify中的ThreadAborted

[英]ThreadAborted in Moq.Verify when using async-await

我的测试方法。 我正在使用xUnit

[Fact]
public async void AccountController_RegisterTest()
{
    const string testEmail = "test@test.com";
    const string testPassword = "test@test.com";

    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).

xUnit不支持async void单元测试AFAIK。 尝试更改单元测试以返回Task

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM