J'aimerais écrire quelque chose comme ceci:
it 'does not invoke any MyService' do MyService.should_not_receive(<any method>) tested_method end
3 Réponses :
Si vous injectez la dépendance code> Myservice CODE> à l'intérieur de votre objet, vous pouvez le substituer avec une simule sans méthodes définies dessus, de sorte que tout appel de méthode augmente une exception.
Permettez-moi de montrer Vous un exemple: p> et les tests seraient les suivants: p>
S'il y avait une raison logique d'entreprise pour sélectionner le service par programme, ce serait une bonne approche, mais je n'aime pas l'idée de le faire juste pour soutenir les tests.
Eh bien, je pense que ces tests vous permettent de comprendre quelles parties de votre code sont strictement couplées les unes aux autres: les comportements difficiles à tester sont généralement plus difficiles à changer. Je pense donc qu'il est bon de prendre des indices de tests.
C'est une généralisation, mais une autre est: Yagni. Il introduit des fonctionnalités qui augmentent la complexité et le «bruit» de la mise en œuvre, qui, si nécessaire pour la demande, ne devrait idéalement pas faire partie de la mise en œuvre.
Bien que j'ai tendance à être d'accord avec vous sur la signification de "difficile à tester", parfois "il est difficile de tester" est vraiment un signe que le système de test a besoin d'une fonctionnalité supplémentaire :).
Je suppose que je peux comprendre votre point de vue, bien que récemment, j'ai été un énorme partisan du principe openclose ( EN.Wikipedia.org/wiki/open/close_principle ), de sorte que cet exemple me frappe comme une architecture" classique "qui devrait être rendue ouverte par extension mais fermée pour la modification. Je suppose que Yagni est une chose, mais j'aime généralement prendre le «risque» de rendre mon design plus flexible, surtout quand cela implique peu d'effort. Mais je suppose que cela implique beaucoup le goût personnel de chacun!
Il s'agit d'une réponse supérieure d'une perspective OO et de conception de code, mais parfois, il existe parfois des limitations qui rendent le double hack (autre réponse) plus appropriée.
Que diriez-vous de remplacer la mise en œuvre avec un double?
RSpec::Mocks::MockExpectationError: Double "should not receive any message" received unexpected message :some_method with (no args)
Cela fonctionne, mais il faut en outre entourer le remplacement et la restauration de myservice avec $ verbose = nil code>,
$ verbose = original_verbosité code> pour supprimer les avertissements lors de la modification de myservice. Mais j'aime cette approche car elle ne nécessite pas de modification de la source d'origine pour soutenir le test.
Si vous utilisez Active_Support est acceptable, vous pouvez également envelopper l'étape de double affectation avec kernel.silence_warnings do code> à partir de
actif_support / core_ext / noyau / rapport Code> Pour gérer avec élégance la suppression.
c'est définitivement une amélioration
it 'does not invoke MyService' do stub_const('MyService', double) tested_method end Any attempt to access MyService will return the mocked RSpec double. Since doubles raise errors when they receive messages that aren't explicitly stubbed (and none are being stubbed) any call to MyService will raise an error.https://relishapp.com/rspec/rspec-mocks/v/3-0/docs/basics/test-doubles