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

#.net #unit-testing #nunit #owin #owin-middleware

#.net #модульное тестирование #nunit #owin #owin-промежуточное программное обеспечение

Вопрос:

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

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

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

 if (context.Response.StatusCode == 400 amp;amp; 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=passwordamp;UserName=fooamp;Password=bar";

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

        var response = _server.HttpClient.SendAsync(request).Resu<

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

Нужно знать, что я здесь делаю не так.

Комментарии:

1. 1) Это интеграционный тест, а не модульный тест. 2) Покажите конфигурацию запуска и полное промежуточное программное обеспечение. 3) Буферизуете ли вы ответ, чтобы иметь к нему доступ по потоку?

Ответ №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 amp;amp; 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 is, это гарантирует, что заголовки будут изменены до отправки заголовков ответа.

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

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