7
votes

RSPEC / Rails: Comment vérifier qu'aucune méthode d'une classe n'est appelée

J'aimerais écrire quelque chose comme ceci:

it 'does not invoke any MyService' do
    MyService.should_not_receive(<any method>)
    tested_method
end


0 commentaires

3 Réponses :


2
votes

Si vous injectez la dépendance Myservice à 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: xxx

et les tests seraient les suivants: xxx


6 commentaires

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.



2
votes

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)


3 commentaires

Cela fonctionne, mais il faut en outre entourer le remplacement et la restauration de myservice avec $ verbose = nil , $ verbose = original_verbosité 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 à partir de actif_support / core_ext / noyau / rapport Pour gérer avec élégance la suppression.


c'est définitivement une amélioration



0
votes
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

0 commentaires