2017-08-21 1 views
3

Ich verwende Moq in .net core (1.1) und habe ein wenig Zeit, dieses Verhalten zu verstehen interweb weist darauf hin, dass dies ohne Probleme funktionieren sollte.Mock gibt Nullwert zurück, wenn ReturnResult ein benutzerdefiniertes Objekt ist, aber funktioniert wie erwartet, wenn es ein primitiver Typ ist bool

Ich habe bereits versucht, mit:

  • Returns (Task.FromResult (...)
  • Returns (Task.FromResult (...)
  • ReturnsAsync (...)

eine IHttpClien t Schnittstelle Mocking PostAsync zu wickeln, PutAsync und GetAsync. Alle diese geben ein ApiResponse Objekt.

var mockClient = new Mock<IHttpClient>(); 

Funktioniert nicht:

mockClient.Setup(x => x.PostAsync(url, JsonConvert.SerializeObject(body), null)) 
            .Returns(Task.FromResult(new ApiResponse())); 

Postsync Definition:

public async Task<ApiResponse> PostAsync(string url, string body, string authToken = null) 

funktioniert:

mockClient.Setup(x => x.PostAsync(url, JsonConvert.SerializeObject(body), null)) 
            .Returns(Task.FromResult(bool)); 

Postsync Definition:

public async Task<bool> PostAsync(string url, string body, string authToken = null) 

Verbrauch:

var api = new ApiService(mockClient.Object); 
var response = api.LoginAsync(body.Username, body.Password); 

UPDATE

[Fact] 
public async void TestLogin() 
{ 
    var mockClient = new Mock<IHttpClient>(); 
    mockClient.Setup(x => x.PostAsync(url, JsonConvert.SerializeObject(body), null)).Returns(Task.FromResult(new ApiResponse())); 

    var api = new ApiService(mockClient.Object); 
    var response = await api.LoginAsync(body.Username, body.Password); 
    Assert.IsTrue(response); 
} 

Rückgabetyp:

public class ApiResponse 
{ 
    public string Content { get; set; } 

    public HttpStatusCode StatusCode { get; set; } 

    public string Reason { get; set; } 
} 

LoginAsync:

public async Task<bool> LoginAsync(string user, string password) 
{ 
    var body = new { Username = user, Password = password }; 
    try 
    { 
     var response = await _http.PostAsync(_login_url, JsonConvert.SerializeObject(body), null); 
     return response .State == 1; 
    } 
    catch (Exception ex) 
    { 
     Logger.Error(ex); 
     return false; 
    } 
} 

PostAsync:

public async Task<object> PostAsync(string url, string body, string authToken = null) 
{ 
    var client = new HttpClient(); 
    var content = new StringContent(body, Encoding.UTF8, "application/json"); 
    var response = await client.PostAsync(new Uri(url), content); 
    var resp = await response.Result.Content.ReadAsStringAsync(); 
    return new ApiResponse 
    { 
     Content = resp, 
     StatusCode = response.Result.StatusCode, 
     Reason = response.Result.ReasonPhrase 
    }; 
} 

Antwort

3

ein einfaches Verfahren unter Test wie diese auf minimalen oben gegebenen Beispiel basierend annimmt.

public class ApiService { 
    private IHttpClient _http; 
    private string _login_url; 

    public ApiService(IHttpClient httpClient) { 
     this._http = httpClient; 
    } 

    public async Task<bool> LoginAsync(string user, string password) { 
     var body = new { Username = user, Password = password }; 
     try { 
      var response = await _http.PostAsync(_login_url, JsonConvert.SerializeObject(body), null); 
      return response.StatusCode == HttpStatusCode.OK; 
     } catch (Exception ex) { 
      //Logger.Error(ex); 
      return false; 
     } 
    } 
} 

Der folgende Test funktioniert, wenn

[Fact] 
public async Task Login_Should_Return_True() { //<-- note the Task and not void 
    //Arrange 
    var mockClient = new Mock<IHttpClient>(); 
    mockClient 
     .Setup(x => x.PostAsync(It.IsAny<string>(), It.IsAny<string>(), null)) 
     .ReturnsAsync(new ApiResponse() { StatusCode = HttpStatusCode.OK }); 

    var api = new ApiService(mockClient.Object); 

    //Act 
    var response = await api.LoginAsync("", ""); 

    //Assert 
    Assert.IsTrue(response); 
} 

Die oben richtig konfiguriert ist nur nur zu Demonstrationszwecken zu zeigen, dass es den Test vorgesehen funktionieren kann richtig konfiguriert ist und übte auf dem erwarteten Verhalten basiert.

Nehmen Sie sich etwas Zeit und überprüfen Sie die Moq quick start, um ein besseres Verständnis für die Verwendung des Frameworks zu erhalten.

+0

Einverstanden. Soweit ich das beurteilen kann, scheint der Hauptunterschied im Setup zu liegen, wo ich die Param-Typen im Vergleich zu Ihrer "richtigen" Einstellung abgeleitet habe. Ich denke, Annahmen können wirklich einen Esel machen. Obwohl ich gerne tiefer eingruppieren würde, warum das, was ich benutzt habe, "inkorrekt" war. ** Sehr geschätzt! ** – Walaitki

+0

@Walaitki moq reagiert direkt auf das, was Sie konfigurieren zu erwarten. Obwohl mein Beispiel sehr einfach war, müssen Sie den moq so einrichten, dass Sie das Verhalten erwarten, das Sie testen möchten. Wenn Sie das Verhalten, das der Schein erwartet, nicht bereitstellen, wird es nicht wie erwartet funktionieren. Um genau zu sagen, warum Ihre nicht funktioniert hat, gibt es nicht genug Details in der Frage. zu viele fehlende Teile zum Puzzle. könnte etwas so einfach und ein falsch platz in einer string. – Nkosi

+0

'It.IsAny' ziemlich gefährlich ** demonstrative ** Beispiel, weißt du :) – VMAtm

Verwandte Themen