2016-03-18 3 views
1

Ich versuche zu testen, dass eine API-Controller-Methode nur Benutzer zurückgibt (plus einige zusätzliche Zustände, die hier nicht relevant sind), die basierend auf Name wo Name = FirstName + ' ' + LastName übereinstimmen.Wie richte ich einen Mock ein, der Ergebnisse basierend auf dem Wert eines Parameters dynamisch zurückgibt?

Ich habe ein Repository, das eine GetUsersByName(name) Methode verfügbar macht. Ich möchte ein Setup für diese Repository-Methode, die eine List<UserModel> mit Benutzern, die die Namen Kriterien aus einigen Stub-Liste von Benutzern (this.testUsers) übereinstimmen zurückgeben.

Ich habe versucht, die folgenden:

this.mockUserReposiotry.Setup(r => r.GetAllUsersByName(It.IsAny<string>())) 
    .Returns(this.mockUtilities.MockUpUserModel(this.testUsers).Where(u => string.Concat(
     u.firstName, " ", u.lastName) 
     .ToLower().Contains()); 

aber ich weiß nicht, wie die Klausel binden zurück zum IsAny<string> enthält, die ich moq sage auf übereinstimmen.

Ist das möglich? Ich vermute, dass ich IsAny mit einem Parameter versorgen muss, aber ich kann keine ähnlichen Beispiele finden.

+0

Ich bin nicht 100% sicher, dass Sie wirklich so auf diese Weise verspotten müssen. Gibt es eine wichtige Logik in Ihrem API-Controller, die von Daten abhängt, die von Ihrem Repository zurückgegeben werden? Z.B. Wenn das Repository Daten zurückgibt, die nicht zur Bedingung passen, behandeln Sie es im API-Controller? –

+2

@ NKosis Antwort ist korrekt, aber als Faustregel sollten Sie zu viel Logik in einem gespielten Verhalten vermeiden. Ich würde willkürliche Werte von SetUp und Assert basierend auf diesen Werten zurückgeben. Nur ein Gedanke, ich kenne dein aktuelles Szenario nicht. –

+0

@Nasmi Sabeer Generell stimme ich zu, aber diese spezifische Methode muss Werte basierend auf bestimmten Kriterien zurückgeben. Wenn ich diese Kriterien nicht vorher definiere, kann ich nicht sicher sein, dass sie in allen Variationen vorhanden sein werden, die ich brauche, wenn der Test ausgeführt wird. – Necoras

Antwort

1

Ja, es ist möglich. Sie können Returns<string> verwenden, die

eine Funktion an, die den Wert berechnen wird von der Methode zurückzukehren, die Argumente für den Aufruf

this.mockUserReposiotry.Setup(r => r.GetAllUsersByName(It.IsAny<string>())) 
    .Returns<string>(originalParameter => this.mockUtilities.MockUpUserModel(this.testUsers).Where(u => string.Concat(
     u.firstName, " ", u.lastName) 
     .ToLower().Contains(originalParameter)); 

Lange Antwort

Abrufen

Ich war in der Lage, einen Beispieltest zu erstellen, um nachzubilden, wonach Sie suchen.

[TestClass] 
public class DynamicResultsTests { 
    List<UserModel> testUsers = new List<UserModel>(); 
    string[] names = new[] { "John Doe", "Jane Doe", "Jack Sprat", "John Smith", "Mary Jane" }; 

    [TestInitialize] 
    public void Init() { 
     testUsers = names.Select(n => { 
      var tokens = n.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); 

      return new UserModel { firstName = tokens[0], lastName = tokens[1] }; 
     }).ToList(); 
    } 

    [TestMethod] 
    public void Test_ShouldDynamicallyReturnResultsBasedOnParameterValue() { 
     //Arrange 
     string parameterValue = "john"; 

     Func<string, UserModel, bool> predicate = (s, u) => string 
       .Join(" ", u.firstName, u.lastName) 
       .IndexOf(s, StringComparison.InvariantCultureIgnoreCase) > -1; 

     Func<string, List<UserModel>> valueFunction = s => 
      this.testUsers.Where(u => predicate(s, u)).ToList(); 

     var mockUserRepository = new Mock<IUserRepository>(); 
     mockUserRepository 
      .Setup(r => r.GetAllUsersByName(It.IsAny<string>())) 
      .Returns<string>(valueFunction); 

     var repository = mockUserRepository.Object; 

     //Act 
     var users = repository.GetAllUsersByName(parameterValue); 

     //Assert (There should be 2 results that match john) 
     users.Should().NotBeNull(); 
     users.Should().NotBeEmpty(); 
     users.Count().Should().Be(2); 
    } 

    public interface IUserRepository { 
     List<UserModel> GetAllUsersByName(string name); 
    } 

    public class UserModel { 
     public string firstName { get; set; } 
     public string lastName { get; set; } 
    } 
} 
+0

Fantastisch. Ich wusste, dass ich in der Nähe war, aber ich brauchte die letzten beiden Stücke. Vielen Dank. – Necoras

Verwandte Themen