Как исправить «ApplicationUserManager is null» при тестировании приложения ASP.NET Web API 2 - PullRequest
0 голосов
/ 18 апреля 2019

Я создаю приложение ASP.NET с контроллером Web Api 2 с аутентификацией.Приложение работает хорошо, я проверял через Почтальон!Я хочу создать модульные тесты с HttpServer / HttpClient, но он не работает.

До этого я не создавал ничего подобного.

AccountController.cs

[RoutePrefix("api/account")]
    public class AccountController : ApiController
    {
        private ApplicationUserManager appUserManager = null;

        protected ApplicationUserManager AppUserManager
        {
            get
            {
                return appUserManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                appUserManager = value;
            }
        }

        private IAuthenticationManager Authentication
        {
            get { return Request.GetOwinContext().Authentication; }
        }

        public AccountController()
        {
        }

        public AccountController(ApplicationUserManager userManager)
        {
            AppUserManager = userManager;
        }

        [HttpGet]
        [Route("users")]
        public IHttpActionResult GetUsers()
        {
            return Ok(AppUserManager.Users.ToList());
        }

        [HttpGet]
        [Route("hello")]
        public IHttpActionResult Hello()
        {
            return Ok();
        }
        ...

IdentityConfig.cs

public class ApplicationUserManager : UserManager<ApplicationUser>
    {
        public ApplicationUserManager(IUserStore<ApplicationUser> store)
            : base(store)
        {
        }

        public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
        {
            var appDbContext = context.Get<ApplicationDbContext>();
            var appUserManager = new ApplicationUserManager(new UserStore<ApplicationUser>(appDbContext));

            return appUserManager;
        }
    }

    public class ApplicationRoleManager : RoleManager<IdentityRole>
    {
        public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
            : base(roleStore)
        {
        }

        public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
        {
            var appDbContext = context.Get<ApplicationDbContext>();
            var appRoleManager = new ApplicationRoleManager(new RoleStore<IdentityRole>(appDbContext));

            return appRoleManager;
        }
    }

Startup.Auth

public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
            });
        }
    }

WebApiConfig.cs

public static void Register(HttpConfiguration config)
        {
            Database.SetInitializer<ApplicationDbContext>(new DbInitializer());

            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }

Startup.cs

    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);           
        }
    }

AccountControllerTests.cs

public class AccountControllerTests
    {
        private HttpServer server;

        public AccountControllerTests()
        {
            var config = new HttpConfiguration();
            WebApiConfig.Register(config);

            config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
            server = new HttpServer(config);
        }

        public HttpRequestMessage CreateRequest(string url, HttpMethod method)
        {
            var request = new HttpRequestMessage();

            request.RequestUri = new Uri(url);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Method = method;

            return request;
        }

        private HttpRequestMessage CreateRequest<T>(string url, HttpMethod method, T content) where T : class
        {
            var request = CreateRequest(url, method);
            request.Content = new ObjectContent<T>(content, new JsonMediaTypeFormatter());

            return request;
        }

        public void Dispose()
        {
            if (server != null)
            {
                server.Dispose();
            }
        }

       [TestMethod]
        public async Task TestGetUsersAsync()
        {
            var client = new HttpClient(server);

            var request = CreateRequest("http://localhost/api/account/users", HttpMethod.Get);

            using (var response = await client.SendAsync(request))
            {
                Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            }

            request.Dispose();
        }

        [TestMethod]
        public async Task TestHelloAsync()
        {
            var client = new HttpClient(server);

            var request = CreateRequest("http://localhost/api/account/hello", HttpMethod.Get);

            using (var response = await client.SendAsync(request))
            {
                Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            }

            request.Dispose();
        }
...

Фактические результаты:

TestGetUsersAsync() - сбой
TestHelloAsync() - пропуск

Я проверил: AppUserManager в AccountController равно нулю Request.GetOwinContext() равно нулю

В чем дело?Ошибка происходит при доступе к базе данных;нужно как-то установить контекст.

Новая информация.HttpContext.Current будет нулевым.HttpContext основан на IIS и не будет установлен при самостоятельном размещении с OWIN. source Не должен использоваться в программе HttpContext.Я изменил:

protected ApplicationUserManager AppUserManager
        {
            get
            {
                return appUserManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                appUserManager = value;
            }
        }

на

protected ApplicationUserManager AppUserManager { get; set; } = new ApplicationUserManager(new UserStore<ApplicationUser>(new ApplicationDbContext()));

все это работает, но я не знаю, как изменить:

        private IAuthenticationManager Authentication => Request.GetOwinContext().Authentication;

???

...