2014-06-11 10 views
6

Mam interfejs z kilkoma metodami. Mam domyślną implementację tego interfejsu. Na potrzeby testów integracyjnych chciałbym stworzyć fałszywą implementację, która zwróci moją wartość niestandardową, jeśli jedna z tych metod zostanie wywołana, a następnie powróci do domyślnej implementacji. Czy to możliwe z Moq, czy też sam powinienem stworzyć prosty stub?Jak mogę zapewnić implementację metod za pomocą Moq?

Przykład

IInterface default = new DefaultImplementation(); 
var mock = new Mock<IInterface>(); 
mock.Setup(i => i.Method(It.IsAny<>())).Calls(p => p==0 ? return 5 : default.Method(p);); 

TheMethodITest(mock.Object()); //if it calls the object with 0 then it should get 5, otherwise it should call the default object 
+0

można podać przykład kodu? – Ian

+0

Nie jest dla mnie jasne, co masz na myśli z * i wraca do domyślnej implementacji inaczej *. Kiedy ta metoda może zostać uruchomiona, jeśli nie zostanie wywołana? –

+0

@Ian, dodany przykład przy użyciu nieistniejących metod do pytania – Grzenio

Odpowiedz

5

Nie jestem pewien, co jest warunkiem dla zapewnienia domyślny lub swoją określoną wartość. Jednak brzmi to tak, jakbyś chciał skonfigurować fałszywą instancję za pomocą Delegator.

public void MoqCanBeSetupWithDelegator() 
{ 
    var mock = new Mock<IInterface>(); 
    Func<string, int> valueFunction = i => i == "true" ? 1 : default(int); 
    mock.Setup(x => x.Method(It.IsAny<string>())).Returns(valueFunction); 

    Assert.Equal(1, mock.Object.Method("true")); 
    Assert.Equal(0, mock.Object.Method("anonymous")); 
} 

public interface IInterface 
{ 
    int Method(string arg); 
} 

Jak widać, metoda Returns jest przeciążony do przyjęcia zwracanych wartości (int) lub Delegator reprezentujący szydzili podpis metody. Możesz użyć Func<string, int>, aby zastąpić rzeczywistą implementację - int Method(string arg).

+0

Ponadto nie jest intuicyjne implementowanie tej funkcji w linii. Aby to osiągnąć, musisz określić typy parametrów w wyrażeniu lambda. Na przykład '... Zwraca ((string i) => i ==" true "? 1: default (int));' Bez określenia '(string i)' kompilator nie może stwierdzić, którą metodę przeciążania próbujesz wywołać . – robbymurphy

+0

Co zrobić, jeśli metoda "zwraca" nieważne? Nie ma metody "Returns()", a następnie ... :( – user2173353

2

Możesz to zrobić, ustawiając próbę na konkretną klasę i używając As(), aby pobrać bazową IInterface, w której konfiguracja jest wykonywana. Można wtedy trudno rzucić mock.Object powołać się na konkretny przedmiot podstawowy:

[Test] 
    public void SomeTest() 
    { 
    var mock = new Mock<DefaultImplementation>().As<IInterface>(); 
    mock.Setup(i => i.Method(It.IsAny<int>())) 
     .Returns<int>(p => p == 0 
           ? 5 
           : ((DefaultImplementation)mock.Object).Method(p)); 

    TheMethodITest(mock.Object); 
    } 

Oto reszta konfiguracji testowanego z, FWIW:

public interface IInterface 
{ 
    int Method(int p); 
} 
public class DefaultImplementation : IInterface 
{ 
    public int Method(int p) 
    { 
     return 6; 
    } 
} 
[TestFixture] 
public class SomeFixture 
{ 
    public static void TheMethodITest(IInterface dep) 
    { 
     for (var i = 0; i < 10; i++) 
     { 
     Debug.WriteLine("{0}:{1}",i, dep.Method(i)); 
     } 
    } 
}