簡體   English   中英

單元測試和多個參數傳遞給Asp.Net Core MVC中的構造函數,將令牌傳遞給每個請求

[英]Unit testing and multiple parameters to constructors in Asp.Net Core MVC, Passing token to every request

我試圖在Asp.Net Core MVC應用程序中向構造函數添加一個參數,但是這樣做有些困難。 這是我的實現。

登錄操作:

[HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public IActionResult Login(LoginViewModel loginModel, string returnUrl = null)
{
   returnUrl = string.IsNullOrWhiteSpace(returnUrl) ? ApiConstants.Dashboard : returnUrl;
   ViewData["ReturnUrl"] = returnUrl;
   if (!ModelState.IsValid) return View(loginModel);
   var token = Service.Login(loginModel);
   if (string.IsNullOrWhiteSpace(token)) return View(loginModel);
   TempData["token"] = token;
   AddCookie(token);
   return RedirectToAction("Index", "Dashboard");
}

private void AddCookie(string token)
{
   HttpContext.Response.Cookies.Append("token", token,new CookieOptions()
   {
      Expires = DateTimeOffset.Now.AddDays(-1)
   });
}

控制器:

private readonly INozzleService _nozzleService;
public NozzleController(INozzleService nozzleService)
{
  var token = HttpContext.Request.Cookies["token"];
  _nozzleService = nozzleService;
}

噴嘴服務:

private static INozzleAdapter Adapter { get; set; }
public NozzleService(INozzleAdapter adapter)
{
  Adapter = adapter;
}

噴嘴適配器:

private readonly string _token;
public NozzleAdapter(string token)
{
   _token = token;
}

在適配器中獲得令牌后,將令牌添加到HttpClient標頭中。

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token);

啟動中的ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
   services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
   services.AddDistributedMemoryCache();
   services.AddSession();
   services.AddTransient<IAccountService, AccountService>();
   services.AddTransient<IAccountAdapter, AccountAdapter>();
   services.AddTransient<INozzleService, NozzleService>();
   services.AddTransient<INozzleAdapter, NozzleAdapter>();
   services.AddMvc();
}

您能否讓我知道在Asp.Net core 2.0 MVC應用程序中實現此目標的最佳方法是什么? 我讀過一篇文章,說在Asp.Net Core MVC應用程序中使用多個構造函數不是一個好主意,因此我不想使用多個構造函數。

同時,我想確保所有類都可以使用DI進行單元測試。 這里最好的方法是什么?

如果有人需要更多信息,請告訴我。

更新:

根據Shyju的解決方案,我能夠實現cookie,但是,仍然需要將兩個參數傳遞給我的一個控制器。

private readonly IAccountService _service;
private readonly ITokenProvider _tokenProvider;
public AccountController(IAccountService service, ITokenProvider tokenProvider)
{
  _service = service;
  _tokenProvider = tokenProvider;
}

因此,可以使用如下所示的AddToken方法。

_tokenProvider.AddToken(token);

您可以考慮抽象邏輯以將令牌獲取到單獨的類,然后根據需要將其注入。

public interface ITokenProvider
{
    /// <summary>
    /// Gets the token
    /// </summary>
    /// <returns></returns>
    string GetToken();
}

現在創建一個實現,它將從cookie中讀取令牌。 這是一個簡單的實現,它從cookie集合中讀取令牌

public class CookieTokenProvider : ITokenProvider
{
    private readonly IHttpContextAccessor httpContextAccessor;

    public CookieTokenProvider(IHttpContextAccessor httpContextAccessor)
    {
        this.httpContextAccessor = httpContextAccessor;
    }
    public string GetToken()
    {
        if (httpContextAccessor.HttpContext.Request.Cookies
                                           .TryGetValue("token", out string tokenValue))
        {
            return tokenValue;
        }
        return null;
    }
}

現在,您可以將ITokenProvider實現注入到ITokenProvider任何位置,並調用GetToken方法以獲取令牌值。 例如,您可以將其注入NozzleAdapter類構造函數。

private readonly ITokenProvider tokenProvider;
public NozzleAdapter(ITokenProvider tokenProvider)
{
   tokenProvider=tokenProvider;
}
public string SomeOtherMethod()
{
   var token = this.tokenProvider.GetToken();
   //Do null check and use it
}

確保在Startup類的ConfigureServices方法中注冊此

services.AddTransient<ITokenProvider, CookieTokenProvider>();

關於您關於獲取令牌和保留令牌的意見,這取決於您要執行的操作。 您可以在CookieTokenProvider實現中執行此操作。 讀取值並將其存儲在某個地方(本地數據庫,內存緩存等)中,如果存在則從那里獲取(下次)

現在,對於單元測試,您可以創建一個不使用HttpContext的MockTokenProvider,而只需為測試返回一個模擬值,

public class MockTokenProvider : ITokenProvider
{
    public string GetToken() => "FakeToken";
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM