【问题标题】:HttpClient default headers not working with Microsoft.Owin.Testing.TestServerHttpClient 默认标头不适用于 Microsoft.Owin.Testing.TestServer
【发布时间】:2017-04-20 17:40:47
【问题描述】:

我正在使用 Microsoft.Owin.Testing 库在内存中集成测试我的 API。我已经添加了 OWIN JWT 中间件以满足我的身份验证需求,现在我正在尝试将生成的令牌传递给需要授权的控制器的测试请求。我可以向您保证,JWT 中间件设置正确,因为它可以正常使用。但是,我观察到 TestServer.HttpClient 对象的一些奇怪行为。当我在 HttpClient 上设置默认授权标头以传递令牌时,我的测试从未通过,因为无法识别令牌。但是,当我使用TestServer.CreateRequest(...) 时,测试正确通过并且令牌被识别。我更喜欢使用 HttpClient 方法,因为它们通过提供的所有扩展方法(例如 PostAsJsonAsync 等)使事情变得非常容易。我开始认为TestServer.HttpClient 中存在错误,或者我完全错过了一些东西。

这是我的测试类(使用 NUnit3):

public class DefinitionsControllerTests
{
    private TestServer _server;
    private string _accessToken;

    [SetUp]
    public void Setup()
    {
        _server = TestServer.Create<Startup>();

        var credentials = new FormUrlEncodedContent(new[] {
            new KeyValuePair<string, string>("grant_type", "password"),
            new KeyValuePair<string, string>("username", "john.doe@mail.com"),
            new KeyValuePair<string, string>("password", "testing123")
        });

        // get token from OWIN JWT middleware
        dynamic resultBody = JObject.Parse(
            _server.HttpClient.PostAsync("/oauth/token", credentials).Result.Content.ReadAsStringAsync().Result);

        _accessToken = (string)resultBody.access_token;

        // this does not appear to ever work
        _server.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken);
    }

    [TearDown]
    public void TearDown()
    {
        _server.Dispose();
    }

    [Test]
    public void GetById_WithExistingId()
    {
        // 401 Unauthorized response everytime and test fails
        var response = _server.HttpClient.GetAsync($"/api/definitions/{expected.Id}").Result;
        var actual = response.Content.ReadAsAsync<Definition>().Result;

        // 200 Ok every time and test passes
        // - these variables aren't part of the test but rather to show alternate request creation method that works
        var response2 = _server.CreateRequest($"/api/definitions/{expected.Id}")
            .AddHeader("Authorization", "Bearer " + _accessToken)
            .GetAsync()
            .Result;
        var actual2 = response.Content.ReadAsAsync<Definition>().Result;

        response.StatusCode.ShouldBe(HttpStatusCode.OK);
        actual.ShouldNotBeNull();
    }

    //...other test methods
}

还有我的控制器:

[Authorize]
public class DefinitionsController : ApiController
{
    private readonly IDefinitionRepository _repo;

    public DefinitionsController(IDefinitionRepository repo)
    {
        _repo = repo;
    }

    public IHttpActionResult Get(Guid id)
    {
        var definition = _repo.Get(id);

        if (definition == null)
            return NotFound();

        return Ok(definition);
    }
}

有人知道为什么只有 CreateRequest() 有效吗?这有点让人生气。

【问题讨论】:

    标签: asp.net-web-api2 integration-testing owin katana


    【解决方案1】:

    问题是 HttpClient 属性每次都返回一个新实例。如果您保存该实例并重新使用它,它将起作用。 https://github.com/aspnet/AspNetKatana/blob/b850cd8b4de61e65bbd7127ce02b5df7c4cb6db5/src/Microsoft.Owin.Testing/TestServer.cs#L48

    【讨论】:

    • 我什至查看了那个源代码,但没有抓住它。解决了,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-03-06
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 2019-03-01
    • 2018-07-15
    相关资源
    最近更新 更多