#.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, это гарантирует, что заголовки будут изменены до отправки заголовков ответа.
Однако я до сих пор понятия не имею, как скрипач подбирал правильный код состояния ответа.
Надеюсь, это кому-то поможет.