Тестовые случаи NUnit, пропускающие промежуточное ПО OWIN

У меня есть OAuthServerProvider, выдающий токены после аутентификации имени пользователя и паролей. Когда имя пользователя или пароль недействительны, я отклоняю owin Context, который по умолчанию возвращает 400 Bad Request в качестве кода состояния.

Но я хочу ответить 401 Unauthorized

Для этого я написал промежуточное ПО, которое проверит заголовок и увидит, присутствует ли пользовательский заголовок, и если да, то заменит код состояния на 401.

if (context.Response.StatusCode == 400 && context.Response.Headers.ContainsKey(Constants.OwinChallengeFlag))
{
   var headerValues = context.Response.Headers.GetValues(Constants.OwinChallengeFlag);
   context.Response.StatusCode = Convert.ToInt16(headerValues.FirstOrDefault());
   context.Response.Headers.Remove(Constants.OwinChallengeFlag);
}

Это работает абсолютно нормально, когда я нажимаю на него с помощью fiddler, но модульный тест, который я написал ниже, всегда получает 400. Каким-то образом, когда я делаю запрос с помощью своего модульного теста, промежуточное программное обеспечение пропускается.

[TestFixture]
public class UnitTest1
{
    private TestServer _server;

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

    [Test]
    public void ShouldReturnUnauthorizedResponse()
    {

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "/token");

        //wrong password 
        var requestContent = "grant_type=password&UserName=foo&Password=bar";

        request.Content = new StringContent(requestContent, Encoding.UTF8, "application/x-www-form-urlencoded");

        var response = _server.HttpClient.SendAsync(request).Result;

        //This assert fails, but shouldn't
        Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.Unauthorized));
    }
}

Нужно знать, что я делаю неправильно здесь.


person Giridhar Karnik    schedule 04.10.2016    source источник
comment
1) Это интеграционный тест, а не модульный. 2) Покажите стартовую конфигурацию и полное промежуточное ПО. 3) Буферизируете ли вы ответ, чтобы иметь доступ к нему в нисходящем направлении?   -  person Nkosi    schedule 04.10.2016


Ответы (1)


Я наконец-то понял....

await _next.Invoke(environment) был виновником. Я вызывал его с тем же объектом словаря среды, который был передан промежуточному программному обеспечению, и, следовательно, изменение, внесенное в объект context, не отражалось в модульном тесте.

Следующий код работает, как и ожидалось....

public async Task Invoke(IDictionary<string, object> environment)
{
    var context = new OwinContext(environment);

    var response = context.Response;

    response.OnSendingHeaders(state =>
    {
        var resp = (OwinResponse)state;
        if (resp.StatusCode == 400 && resp.Headers.ContainsKey(Constants.OwinChallengeFlag))
        {
            var headerValues = context.Response.Headers.GetValues(Constants.OwinChallengeFlag);
            resp.StatusCode = Convert.ToInt16(headerValues.FirstOrDefault());
            resp.ReasonPhrase = HttpStatusCode.Unauthorized.ToString();
            resp.Headers.Remove(Constants.OwinChallengeFlag);
        }
    }, response);

    await _next.Invoke(context.Environment);
}

Помимо передачи переменной environment, полученной из измененного объекта context, важно изменить заголовок ответа внутри response.OnSendingHeaders, это гарантирует, что заголовки будут изменены до отправки заголовков ответа.

Однако я до сих пор понятия не имею, как скрипач набирал правильный код состояния ответа.

Надеюсь, это поможет кому-то.

person Giridhar Karnik    schedule 05.10.2016