2014-06-25 18 views
6

Quando si utilizza Moq con Verifica, per affermare che è stato chiamato un determinato metodo con parametri specificati, è possibile un diverso tipo di sintassi; una è la "E" la sintassi, come questoMoq Verifica senza di esso - che tipo di confronto?

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

Quello che succede qui è che il parametro che SomeMethod si chiama con, è controllato per l'uguaglianza con ExpectedString. Un'altra possibile sintassi è senza "It":

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

che dovrebbe dare lo stesso risultato. Da quello che sono stato in grado di trovare su diversi forum, la differenza è che quest'ultimo è un controllo di identificazione (riferimento equivale) (tranne che per i tipi di valore).

Tuttavia, la mia domanda è quando il parametro è di tipo Tipo di raccolta. NET, Equals su Collection<T> è solo ereditato da object, quindi il seguente verifica:

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

non dovrebbe essere possibile passare, dato che la raccolta è un'istanza nella verifica, e quindi non può eventualmente essere la stessa istanza questo è istanziato nel codice di produzione. Tuttavia, funziona, il che indica che Moq fa un CollectionAssert o qualcosa del genere, contrariamente alle informazioni che ho potuto trovare.

Ecco un esempio di codice che illustra il comportamento, il test passa, ma penso che dovrebbe fallire se Moq avesse usato il confronto di uguaglianza di riferimento.

[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 }); 
    } 
} 

Qualcuno sa se questo comportamento è previsto per Moq (versione 4.1)? Il comportamento è cambiato a un certo livello di versione?

risposta

5

Questo è desired behaviour ed era added to moq in January 2009 (versione 3.0.203.1).

Se moq trova uno IEnumerable, utilizza SequenceEqual per confrontare l'argomento effettivo e l'argomento utilizzato nell'impostazione, altrimenti utilizza solo Equals.

Here's la relativa porzione di codice:

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>()); 
    } 
} 
Problemi correlati