2016-09-30 2 views
2

У меня есть этот код, и я не могу заставить HTTPClient возвращать ответ строки, несмотря ни на что.Аргумент соответствия не работает должным образом с NSubstitute

HttpClient httpClient = Substitute.For<HttpClient>(); 

httpClient.PostAsync("/login", Arg.Any<StringContent>()) 
      .Returns(this.StringResponse("{\"token\": \"token_content\"}")); 

Console.WriteLine(await httpClient.PostAsync("/login", new StringContent(string.Empty)) == null); // True 

Вот метод StringResponse, если кто-то хочет, чтобы воспроизвести это:

private HttpResponseMessage StringResponse(string content) 
{ 
    var response = new HttpResponseMessage(HttpStatusCode.OK); 

    if (content != null) 
    { 
     response.Content = new StringContent(content); 
    } 

    return response; 
} 

Что я делаю неправильно?

Это работает, когда я

httpClient.PostAsync("/login", Arg.Any<StringContent>()) 
       .ReturnsForAnyArgs(this.StringResponse("{\"token\": \"token_content\"}")); 

Но мне не нужен только какие-либо аргументы, мне нужно одну из них, чтобы быть строкой "/login", а другие быть типа StringContent.

Я попытался поставить что-то более общее в Arg.Is звоните как HttpContent, но это тоже не работает.

Я использую NSubstitute 2.0.0-rc на .NET Core, но я также попытался использовать NSubstitute 1.10.0 в стандартном приложении консоли и получил тот же результат.

+0

Какую версию nsubstitute вы используете? (Я пытаюсь воспроизвести проблему сейчас.) –

+0

Я использую 2.0.0-rc с .Net Core, но пробовал этот код с 1.10.0 в обычном консольном приложении и получил тот же результат. –

+0

Хм. Воспроизвел его, но еще не удалось его исправить ... –

ответ

4

Проблема заключается в том, что метод public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content) не является виртуальным, и NSubstitute не может правильно связать спецификацию аргумента и вернуть значение методу. Это проблема всех насмешливых библиотек на основе Castle.Core.

Важно, чтобы NSubstitute привязывал спецификацию к первому виртуальному методу в стеке выполнения, который оказывается в методе public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) где-то в стеке. Вы были «счастливы» иметь тот же тип возврата в нем. И, как вы видите, у него разные аргументы, которые явно не соответствуют тем, которые вы предоставили. Удивительно ReturnsForAnyArgs() работает, потому что он не проверяет спецификацию аргумента, которую вы предоставили.

+0

Я бы никогда не подумал об этом сам, спасибо! –

Смежные вопросы