6
votes

Comment puis-je vous moquer d'une ressource automatiquement fermeable correctement?

J'essaie d'écrire un test d'unité pour cela: XXX PRE>

Dans mon test, je me moque de l'aide (en utilisant Mockito) et dites helper.createcharannel () pour renvoyer un canal moqueur . P>

Ce test échoue avec p>

@Mock
private InetAddress peerAddress;
@Mock
private UDPChannelHelper helper;
@Mock
private DatagramChannel channel;

private UDPTransportImpl transport;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
    when(helper.createChannel()).thenReturn(channel);
    transport = new UDPTransportImpl(peerAddress, 0, helper);
}

@Test
public void testNormalSubmit() throws Exception {
    transport.submit("Hello");
}


4 commentaires

Pouvez-vous montrer votre code sur lequel vous vous moquez? Vous avez également débogué et confirmé que A) Helper est en fait une simulation, B) Helper.createcharannel () renvoie également un objet moqué?


Ajout du code de test et oui, dans le débogueur, à la fois assistant et canal sont du type Blablabla $$ $$ Enhancerbymockitowithcglib.


Cette page: Mockito.googlecode .Com / SVN / Tags / Dernier / Javadoc / Org / Mockito / ... déclare explicitement "que des méthodes annulées sur des simulacres ne font rien par défaut!". Nous ne pouvons donc supposer que le blocage enfin n'exécute pas sur un moqueur. Votre code me semble bien, alors je ne suis pas sûr de savoir pourquoi c'est..vous n'auront certainement pas besoin de la sous-claplacement vous-même.


Une chose à essayer, mettez un point de rupture à l'intérieur du bloc d'essai. Ensuite, à Eclipse Aller à la vue de débogage, d'abord triple chèque que la chaîne est une simule, puis des expressions goto. Entrez le canal.FLOSE () et exécutez-le et voyez quel est le résultat de ceci.


3 Réponses :


8
votes

Vous vous moquez d'une classe réelle datagramcannel , qui s'étend abstractinterruptiblechannel . Cependant, le abstractinterrectiblechannel.close est final et Mockito ne peut pas actuellement simuler le code final. Ce qui explique pourquoi vous avez une NPE dans le code.

Je dois vous rappeler qu'il est communément admis que des types moqueurs que vous ne possédez pas est une mauvaise pratique. J'ai vu des gens le faire et ils avaient des mauvaises surprises des années plus tard, lorsque la réelle mise en œuvre avait changé, mais le comportement masculin ne pensait pas, alors ils pensaient à tort tout allait bien quand ils ont mis à jour la version des bibliothèques.

Néanmoins si vous voulez continuer de cette façon, car vous avez des raisons valables de cela (et il y en a certains), vous pouvez retourner une simule d'interface, comme canal qui s'étend réellement Classable . Ou vous pouvez utiliser toute autre interface que vous devez interagir avec celle qui était présente dans datagramChannel . De plus, si vous avez besoin de plus d'une interface, utilisez simplement Mock (Channel.Class, avec remplissage (). ExtrainterFaces (...)) .

espère que cela aide Acclamations, Brice


2 commentaires

Si vous ne possédez pas de morceaux que vous ne possédez pas est une mauvaise pratique, puis obtenir une couverture à 100% avec des tests unitaires est généralement impossible sans la mauvaise pratique ... (je suppose que les tests d'unité doivent être isolés de toute autre chose externe)


@ Tomaszposłuszny dans mon expérience réalisant une couverture à 100% avec un test unitaire atteint trop de raisons pour d'autres raisons que de bon design. Cependant, je crois que le test d'acceptation / d'intégration peut bien compléter ceux-ci pour couvrir la majeure partie du pourcentage restant. Néanmoins, cette réponse a été écrite en 2013 avec Mockito 1.x sans moquer finale, maintenant avec V3.x se moquant de ces types / méthodes finales devrait être possible.



1
votes

Mis de côté si vous devriez faire cela ou non, une façon dont vous pouvez contourner ce problème consiste à "fixer" l'instance de faux abstractinterruptiblechannel (si un fichier FileChannel, un datagramnon, etc.) en fournissant un objet pour le Closelock Champ utilisé pour synchroniser l'appel de fermeture. XXX

Préparez-vous à résoudre le code ci-dessus sur les versions de Java mineures, car la mise en œuvre interne de Abstractinterruptiblechannel pourrait changer.


0 commentaires

2
votes

J'ai eu le même problème et j'utilise Spy (..) au lieu de simuler (..) a travaillé pour moi. J'essayais de simuler une erreur lors de la tronquage d'un fichier et mon système manipulait l'erreur en conséquence.

FileChannel fileChannel = spy(FileChannel.class);
mockStatic(FileChannel.class);
when(FileChannel.open(eq(filePath), eq(StandardOpenOption.WRITE))).thenReturn(fileChannel);
when(fileChannel.truncate(1000L)).thenThrow(new IOException("Unable to truncate file"));

...

// Snippet being tested!
fileChannel = FileChannel.open(filePath, StandardOpenOption.WRITE);
fileChannel.truncate(1000L); // Will throw the exception!


1 commentaires

C'est la solution la plus simple, en utilisant espion (...) au lieu de mock (...) a résolu ce problème de référence nul pour moi. Merci!