2016-10-04 8 views
0

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

Но я хочу, чтобы ответить 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); 
} 

Это работает отлично, когда я ударил его скрипачом, но единичный тест, который я написал ниже, всегда получает 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)); 
    } 
} 

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

+0

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

ответ

0

я, наконец, понял это ....

await _next.Invoke(environment) был виновником. Я вызывал его с той же средой Word Object, которая была передана в промежуточное программное обеспечение, и, следовательно, модификация объекта 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 имеет важное значение, это гарантирует, что заголовки изменены перед отправляются ответные заголовки.

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

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