2012-06-30 7 views
16

Ich hatte ein paar Gelegenheiten, wo so etwas hilfreich wäre. Ich habe zum Beispiel eine AccountCreator mit einer Create Methode, die eine NewAccount dauert. Meine AccountCreator hat eine IRepository, die schließlich verwendet wird, um das Konto zu erstellen. Mein AccountCreator wird zuerst die Eigenschaften von NewAccount bis Account abbilden, zweitens die Account an den Repo übergeben, um es endlich zu erstellen. Meine Tests in etwa so aussehen:Wie kann moq verwendet werden, um zu überprüfen, ob ein ähnliches Objekt als Argument übergeben wurde?

public class when_creating_an_account 
{ 
    static Mock<IRepository> _mockedRepository; 
    static AccountCreator _accountCreator; 
    static NewAccount _newAccount; 
    static Account _result; 
    static Account _account; 

    Establish context =() => 
     { 
      _mockedRepository = new Mock<IRepository>(); 
      _accountCreator = new AccountCreator(_mockedRepository.Object); 

      _newAccount = new NewAccount(); 
      _account = new Account(); 

      _mockedRepository 
       .Setup(x => x.Create(Moq.It.IsAny<Account>())) 
       .Returns(_account); 
     }; 

    Because of =() => _result = _accountCreator.Create(_newAccount); 

    It should_create_the_account_in_the_repository =() => _result.ShouldEqual(_account); 
} 

Also, was ich brauche, ist etwas It.IsAny<Account> zu ersetzen, denn das hilft mir nicht überprüfen, ob das richtige Konto erstellt wurde. Was wäre erstaunlich ist so etwas wie ...

public class when_creating_an_account 
{ 
    static Mock<IRepository> _mockedRepository; 
    static AccountCreator _accountCreator; 
    static NewAccount _newAccount; 
    static Account _result; 
    static Account _account; 

    Establish context =() => 
     { 
      _mockedRepository = new Mock<IRepository>(); 
      _accountCreator = new AccountCreator(_mockedRepository.Object); 

      _newAccount = new NewAccount 
       { 
        //full of populated properties 
       }; 
      _account = new Account 
       { 
        //matching properties to verify correct mapping 
       }; 

      _mockedRepository 
       .Setup(x => x.Create(Moq.It.IsLike<Account>(_account))) 
       .Returns(_account); 
     }; 

    Because of =() => _result = _accountCreator.Create(_newAccount); 

    It should_create_the_account_in_the_repository =() => _result.ShouldEqual(_account); 
} 

Hinweis I It.IsAny<> zu It.IsLike<> geändert und in einem bevölkerten Account-Objekt übergeben. Idealerweise vergleicht etwas im Hintergrund die Eigenschaftswerte und lässt sie passieren, wenn sie alle übereinstimmen.

Also existiert es schon? Oder ist das vielleicht etwas, das Sie schon einmal gemacht haben und es Ihnen nichts ausmacht, den Code zu teilen?

+1

Moq unterstützt benutzerdefinierte Matcher - wie in, Sie benutzerdefinierten comparers verwendet haben können, wenn Argumente für einen Anruf passend , aber das musst du selbst umsetzen. Siehe Beispiel [hier] (http://stackoverflow.com/a/10300051/343266). –

Antwort

20

Um einen Repository Stub einen bestimmten Wert zurückzukehren, basierend auf wie Kriterien, sollte folgende Arbeiten:

_repositoryStub 
    .Setup(x => x.Create(
     Moq.It.Is<Account>(a => _maskAccount.ToExpectedObject().Equals(a)))) 
    .Returns(_account); 
+0

Nun, das ist, was ich gesucht habe! Danke Derek! –

+3

Falls jemand über diese Antwort gestolpert ist und dasselbe versuchen möchte, müssen Sie die ExpectedObjects-Bibliothek einbinden. https://github.com/derekgreer/expectedObjects oder 'install-package ExpectedObjects' –

12

Die folgende Beschreibung ist für Sie arbeiten:

Moq.It.Is<Account>(a=>a.Property1 == _account.Property1) 

jedoch, wie es erwähnt wurde Sie haben passende Kriterien zu implementieren.

+0

Ich benutze das jeden Tag. Aber stell dir vor, "a" ist eine Klasse mit 50 Eigenschaften. Ich wäre eher in der Lage, das erwartete Objektmuster zu verwenden, um das tatsächliche Objekt (mit all seinen Eigenschaften) mit einem erwarteten Objekt (mit allen erwarteten Eigenschaften) zu vergleichen. Dafür halte ich mich bereit. –

0

Ich konnte nichts finden, was genau das tut, was in der Frage beschrieben wird. In der Zwischenzeit ist der beste Weg, um Verifikation von Objekten, die als Argumente zu verspotteten Methoden (ohne den Luxus der Referenzgleichheit) übergeben wurde, eine Kombination von Callback und das Expected Object Muster zu vergleichen, um das tatsächliche mit dem erwarteten Objekt zu vergleichen:

public class when_creating_an_account 
{ 
    static Mock<IRepository> _mockedRepository; 
    static AccountCreator _accountCreator; 
    static NewAccount _newAccount; 
    static Account _result; 
    static Account _expectedAccount; 
    static Account _actualAccount; 

    Establish context =() => 
     { 
      _mockedRepository = new Mock<IRepository>(); 
      _accountCreator = new AccountCreator(_mockedRepository.Object); 

      _newAccount = new NewAccount 
       { 
        //full of populated properties 
       }; 
      _expectedAccount = new Account 
       { 
        //matching properties to verify correct mapping 
       }; 

      _mockedRepository 
       .Setup(x => x.Create(Moq.It.IsAny<Account>(_account))) 
       //here, we capture the actual account passed in. 
       .Callback<Account>(x=> _actualAccount = x) 
       .Returns(_account); 
     }; 

    Because of =() => _result = _accountCreator.Create(_newAccount); 

    It should_create_the_account_in_the_repository = 
     () => _result.ShouldEqual(_account); 

    It should_create_the_expected_account = 
     () => _expectedAccount.ToExpectedObject().ShouldEqual(_actualAccount); 
} 

Das erwartete Objektmuster ist groß, aber es ist kompliziert in C# zu implementieren, so dass ich eine Bibliothek, die alles, was für mich behandelt. https://github.com/derekgreer/expectedObjects

Meine letzte Beobachtung betrachtet die Eigenschaften in dem tatsächlichen Konto, das übergeben wird, und vergleicht jedes mit derselben Eigenschaft auf meinem "erwarteten Objekt". Auf diese Weise habe ich keine riesige Liste von Mock-Eigenschaftsprüfungen, noch habe ich eine Tonne von Testbeobachtungen.

Verwandte Themen