2014-06-25 12 views
6

Podczas korzystania z Moq z Weryfikacja, aby potwierdzić, że pewna metoda została wywołana z określonymi parametrami, możliwy jest inny rodzaj składni; jeden jest „on” składnia, jak toMoq Weryfikuj bez It - jakiego rodzaju porównać?

mock.Verify(c => c.SomeMethod(It.Is<string>(s => s == ExpectedString))); 

Co się dzieje jest to, że parametr, który SomeMethod nazywa się, jest sprawdzana pod kątem równości z ExpectedString. Inna możliwa składnia jest bez "It":

mock.Verify(c => c.SomeMethod(ExpectedString)); 

, która powinna dawać taki sam wynik. Z tego, co udało mi się znaleźć na różnych forach, różnica polega na tym, że ta ostatnia jest sprawdzianem identyfikującym (odniesienie równe) (z wyjątkiem typów wartości).

Jednak moje pytanie dotyczy momentu, w którym parametr jest typu Typ kolekcji. W .NET Equals na Collection<T> właśnie odziedziczony object, więc następuje sprawdzenie:

mock.Verify(c => c.SomeMethod(new Collection<string> { ExpectedString })); 

nie powinno być możliwe do przekazania, biorąc pod uwagę, że kolekcja jest tworzony w zweryfikować, a zatem nie może być może być taka sama instancja to jest tworzone w kodzie produkcyjnym. Niemniej jednak działa, co oznacza, że ​​Moq robi CollectionAssert lub coś podobnego, w przeciwieństwie do informacji, które mogłem znaleźć.

Oto przykład kodu, który ilustruje zachowanie, test przechodzi, ale myślę, że powinien się nie powieść, jeśli Moq użył porównania odniesienia.

[TestMethod] 
public void Test() 
{ 
    var mock = new Mock<IPrint>(); 
    const int ExpectedParam = 1; 
    var test = new TestPrinter { Printer = mock.Object, Expected = ExpectedParam }; 

    test.Do(); 

    mock.Verify(c => c.Print(new Collection<int> { ExpectedParam })); 
} 

public interface IPrint 
{ 
    void Print(Collection<int> numbers); 
} 

public class TestPrinter 
{ 
    public IPrint Printer { get; set; } 

    public int Expected { get; set; } 

    public void Do() 
    { 
     Printer.Print(new Collection<int> { Expected }); 
    } 
} 

Czy ktoś wie, czy jest to oczekiwane zachowanie Moq (wersja 4.1)? Czy zachowanie zostało zmienione na pewnym poziomie wersji?

Odpowiedz

5

To jest desired behaviour i był added to moq in January 2009 (wersja 3.0.203.1).

Jeśli moq znajdzie numer IEnumerable, używa on SequenceEqual do porównania rzeczywistego argumentu i argumentu użytego w konfiguracji, w przeciwnym razie używa tylko Equals.

Here's odpowiedni fragment kodu:

internal class ConstantMatcher : IMatcher 
{ 
    ... 

    public bool Matches(object value) 
    { 
     if (object.Equals(constantValue, value)) 
     { 
      return true; 
     } 

     if (this.constantValue is IEnumerable && value is IEnumerable) 
     { 
      return this.MatchesEnumerable(value); 
     } 

     return false; 
    } 

    private bool MatchesEnumerable(object value) 
    { 
     var constValues = (IEnumerable)constantValue; 
     var values = (IEnumerable)value; 
     return constValues.Cast<object>().SequenceEqual(values.Cast<object>()); 
    } 
} 
Powiązane problemy