2010-09-24 7 views
5

J'ai la signature de la méthode suivante dans mon iterface:NSubstitute prend-il en charge les paramètres ref?

void SetItem(ref AddressItem item); 

je fais une contrainte de paramètre comme ceci:

IAddAddressForm form = Substitute.For<IAddAddressForm>(); 
AddressItem item = null; 
form.SetItem(Arg.Is(item)); 

Mais cela échoue à cause de l'arbitre. Si je prends le ref, alors ça marche bien. Mais je dois passer par référence ici.

Des idées pour l'obtenir? Side Note: Mon but ultime est de lancer une exception dans SetItem si la valeur passée est null. Si vous pouvez aider avec cela, vous obtenez des points supplémentaires!

+0

Je suis vraiment curieux de savoir pourquoi vous devez utiliser 'ref' ici. Pouvez-vous s'il vous plaît expliquer? –

+0

Eh bien, je fais un exemple de projet pour former mon département informatique sur les tests unitaires utilisant NSubstitute et Moles. Dans le cadre de ce que je veux mole Linq-To-SQL. Pour ce faire, j'ai dû effectuer une mise à jour vers un objet renvoyé par une requête Linq-to-sql. J'ai trouvé que si je ne passais pas l'objet avec le 'ref' alors la mise à jour a échoué (Parce qu'il ne recongnized plus l'objet comme celui demandé.) Cela peut ne pas être la" meilleure pratique "pour linq à sql, mais je suis test de l'unité de formation, pas Linq. – Vaccano

+0

Vous pouvez voir la question/réponse qui a conduit à mon code étant comme ça ici: http://stackoverflow.com/questions/3766417/save-changes-in-linq-to-sql/3770482#3770482 – Vaccano

Répondre

10

NSubstitute ne prend pas directement en charge les paramètres de correspondance d'arg, mais en général, il fonctionne avec eux.

Je vais supposer que vous devez utiliser ref comme indiqué dans votre question, mais évidemment si vous pouvez éviter ref votre API sera plus simple, tout comme le tester (indépendamment des cadres que vous utilisez).

En réponse à votre question immédiate, vous pouvez passer un ref en mettant à jour votre deuxième exemple de code à:

form.SetItem(ref item); 

Pour votre note côté, assurez-vous que vous essayez de ne pas trop pousser le comportement dans votre substitut . J'ai constaté que chaque fois que je fais cela, c'est un signe dont j'ai besoin pour simplifier la communication entre la classe que je suis en train de tester et ses dépendances. (Ou si j'ai vraiment besoin de beaucoup de logique dans un faux objet, je vais en programmer un plutôt que de le générer, cela peut souvent être plus simple.)

Il existe plusieurs façons d'obtenir cet appel pour lancer une exception :

form.When(x => x.SetItem(ref item)).Do(x => { throw new ArgumentNullException(); }); 

Ceci déclenchera une exception uniquement s'il est appelé avec une référence nulle. Vous pouvez également ajouter ce comportement de manière sélective en fonction de l'argument adopté, bien que je vous déconseille car c'est probablement un signe que vous insistez trop sur votre remplaçant.

form.WhenForAnyArgs(x => x.SetItem(ref item)) 
    .Do(x => { 
     if (x[0] == null) 
      throw new ArgumentNullException(); 
    }); 

Enfin, si vous voulez simplement vérifier que la classe que vous testez répond correctement lorsque IAddAddressForm lance une exception arg nulle, je ferais probablement ceci:

form 
    .WhenForAnyArgs(x => x.SetItem(ref item)) 
    .Do(x => { throw new ArgumentNullException(); }); 

De cette façon, vous n Peu importe ce que l'argument est, vous voulez juste vous assurer que le code que vous testez réagit correctement à ce cas.

Espérons que cela aide.

SIDE NOTE:

Si vous souhaitez utiliser un matcher arg (comme Arg.Any<AddressItem>()) pour un argument out ou ref vous devrez définir en dehors de l'appel lui-même (cela peut être un peu d'erreurs : vous devrez vous assurer que vous définissez les coupleurs dans le même ordre que dans l'appel):

 IAddAddressForm form = Substitute.For<IAddAddressForm>(); 
     AddressItem item = Arg.Is<AddressItem>(y => y.Number == 14); 
     form 
      .When(x => x.SetItem(ref item)) 
      .Do(x => { throw new ArgumentNullException(); }); 
     var address = new AddressItem { Number = 14 }; 
     form.SetItem(ref address); 
+0

Réponse très complète! Merci beaucoup. On dirait que je fais beaucoup de choses dans mes remplaçants, mais c'est parce que je fais une formation pour mes collègues et que mes exemples sont un peu artificiels. – Vaccano

Questions connexes