2012-10-13 11 views
25

Chciałbym ustawić metodę z Moq dwukrotnie, ale wydaje się, że ostatnia nadpisuje poprzednie. Oto moja początkowa konfiguracja:Jak ustawić metodę dwukrotnie dla różnych parametrów z próbą

string username = "foo"; 
string password = "bar"; 

var principal = new GenericPrincipal(
    new GenericIdentity(username), 
    new[] { "Admin" }); 

var membershipServiceMock = new Mock<IMembershipService>(); 
membershipServiceMock.Setup(ms => 
    ms.ValidateUser(username, password) 
).Returns(new ValidUserContext { 
    Principal = principal 
}); 

ta działa obecnie w porządku, ale chcę to wrócić new ValidUserContext() jeżeli nazwa użytkownika lub hasło jest raczej niż username i password zmiennych jak wyżej. Aby to zrobić, dodałem inną konfigurację, ale tym razem to nadpisuje nad jednym i zawsze stosuje się go:

membershipServiceMock.Setup(ms => 
    ms.ValidateUser(It.IsAny<string>(), It.IsAny<string>()) 
).Returns(
    new ValidUserContext() 
); 

Jaki jest najbardziej elegancki sposób obsługi tego typu sytuacjach Min?

Edit

I rozwiązać problem z poniższej podejścia, ale myślę, że istnieje lepszy sposób obsługi to:

var membershipServiceMock = new Mock<IMembershipService>(); 
membershipServiceMock.Setup(ms => 
    ms.ValidateUser(It.IsAny<string>(), It.IsAny<string>()) 
).Returns<string, string>((u, p) => 
    (u == username && p == password) ? 
    new ValidUserContext { 
     Principal = principal 
    } 
    : new ValidUserContext() 
); 

Odpowiedz

35

Moq obsługuje ten z pudełka z ograniczeniami Argument:

mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u == username), It.Is<string>(p => p == password)) 
    .Returns(new ValidUserContext { Principal = principal }); 
mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u != username), It.Is<string>(p => p != password)) 
    .Returns(new ValidUserContext()); 

Catch-allIt.IsAny także działa, ale kolejność jest ważna:

// general constraint first so that it doesn't overwrite more specific ones 
mock.Setup(ms => ms.ValidateUser(
     It.IsAny<string>(), It.IsAny<string>()) 
    .Returns(new ValidUserContext()); 
mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u == username), It.Is<string>(p => p == password)) 
    .Returns(new ValidUserContext { Principal = principal }); 
+1

Pierwsze rozwiązanie nie obsługuje przypadku, gdy u == nazwa użytkownika i p! = Hasło, czy to prawda? –

2

Inną z opcji skrzynki jest użycie Powrót <> Wersja do powrotu różne ValidUserContexts zależności od parametrów. To nie jest lepsze niż powyższa odpowiedź, tylko kolejna opcja.

Ustawiamy ValidateUser(), aby zwracał wynik funkcji GetUserContext (string, string), przekazując nazwę użytkownika i hasło, z którymi wywołano ValidateUser().

[TestClass] 
public class MultipleReturnValues { 

    public class ValidUserContext { 
     public string Principal { get; set; } 
    } 

    public interface IMembershipService { 
     ValidUserContext ValidateUser(string name, string password); 
    } 

    [TestMethod] 
    public void DifferentPricipals() { 

     var mock = new Mock<IMembershipService>(); 
     mock.Setup(mk => mk.ValidateUser(It.IsAny<string>(), It.IsAny<string>())).Returns<string, string>(GetUserContext); 

     var validUserContext = mock.Object.ValidateUser("abc", "cde"); 

     Assert.IsNull(validUserContext.Principal); 


     validUserContext = mock.Object.ValidateUser("foo", "bar"); 

     Assert.AreEqual(sPrincipal, validUserContext.Principal); 


    } 

    private static string sPrincipal = "A Principal"; 
    private static ValidUserContext GetUserContext(string name, string password) { 

     var ret = new ValidUserContext(); 

     if (name == "foo" && password == "bar") { 
      ret = new ValidUserContext { Principal = sPrincipal }; 
     } 
     return ret; 

    } 
} 
Powiązane problemy