Méthodes d’extension moqueuses avec Moq

J’ai une interface préexistante …

public interface ISomeInterface { void SomeMethod(); } 

et j’ai étendu cette insortinggue en utilisant un mixin …

 public static class SomeInterfaceExtensions { public static void AnotherMethod(this ISomeInterface someInterface) { // Implementation here } } 

J’ai une classe qui appelle cela que je veux tester …

 public class Caller { private readonly ISomeInterface someInterface; public Caller(ISomeInterface someInterface) { this.someInterface = someInterface; } public void Main() { someInterface.AnotherMethod(); } } 

et un test où je voudrais simuler l’interface et vérifier l’appel à la méthode d’extension …

  [Test] public void Main_BasicCall_CallsAnotherMethod() { // Arrange var someInterfaceMock = new Mock(); someInterfaceMock.Setup(x => x.AnotherMethod()).Verifiable(); var caller = new Caller(someInterfaceMock.Object); // Act caller.Main(); // Assert someInterfaceMock.Verify(); } 

L’exécution de ce test génère cependant une exception …

 System.ArgumentException: Invalid setup on a non-member method: x => x.AnotherMethod() 

Ma question est la suivante: y a-t-il un bon moyen de simuler l’appel mixin?

Vous ne pouvez pas “directement” simuler la méthode statique (donc la méthode d’extension) avec un cadre moqueur. Vous pouvez essayer Moles ( http://research.microsoft.com/en-us/projects/pex/downloads.aspx ), un outil gratuit de Microsoft qui implémente une approche différente. Voici la description de l’outil:

Moles est une infrastructure légère pour les stubs de test et les détours dans .NET basée sur des delegates.

Les taupes peuvent être utilisées pour détourner toute méthode .NET, y compris les méthodes non virtuelles / statiques dans les types scellés.

Vous pouvez utiliser Moles avec n’importe quel framework de test (c’est indépendant à ce sujet).

J’ai utilisé un wrapper pour contourner ce problème. Créez un object wrapper et passez votre méthode simulée.

Voir « Méthodes statiques moqueuses pour les tests unitaires» de Paul Irwin.

J’ai trouvé que je devais découvrir l’intérieur de la méthode d’extension pour laquelle je tentais de me moquer de l’entrée et me moquer de ce qui se passait dans l’extension.

J’ai consulté en utilisant une extension pour append du code directement à votre méthode. Cela signifie que je n’ai pas besoin de me moquer de ce qui se passe à l’intérieur de l’extension plutôt que de l’extension elle-même.

J’aime utiliser le wrapper (modèle d’adaptateur) lorsque j’emballe l’object lui-même. Je ne suis pas sûr d’utiliser cela pour envelopper une méthode d’extension, qui ne fait pas partie de l’object.

J’utilise une propriété interne injectable paresseuse de type Action, Func, Predicate ou déléguer et permet d’injecter (échanger) la méthode lors d’un test unitaire.

  internal Func DoWorkMethod { [ExcludeFromCodeCoverage] get { return _DoWorkMethod ?? (_DoWorkMethod = (obj, val) => { return obj.DoWork(val); }); } set { _DoWorkMethod = value; } } private Func _DoWorkMethod; 

Ensuite, vous appelez le Func au lieu de la méthode réelle.

  public object SomeFunction() { var val = "doesn't matter for this example"; return DoWorkMethod.Invoke(MyObjectProperty, val); } 

Pour un exemple plus complet, consultez http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/