Comment nettoyer les simulacres lors des tests de printemps lors de l'utilisation de Mockito
Je suis assez nouveau à Mockito et avoir de la difficulté à nettoyer.
J'ai l'habitude d'utiliser JMock2 pour les tests unitaires. Autant que je sache, JMock2 préserve les attentes et les autres se moquer de l'information dans un contexte qui sera reconstruit pour chaque méthode de test. Par conséquent, chaque méthode de test n'est pas perturbé par les autres.
J'ai adopté la même stratégie pour le printemps des tests lors de l'utilisation de JMock2, j'ai trouvé un problème potentiel avec les stratégies que j'ai utilisé dans mon post: Le contexte de l'application est reconstruit pour chaque méthode de test et donc ralentit l'ensemble de la procédure de test.
J'ai remarqué de nombreux articles vous recommandons d'utiliser Mockito au printemps tests et je voudrais avoir un essai. Il fonctionne bien jusqu'à ce que j'écris deux méthode d'essai dans un cas de test. Chaque méthode de test passé quand il a couru seul, l'Un d'eux n'a pas si ils ont couru ensemble. J'ai spéculé que c'est parce que la fausse information a été préservée dans la maquette elle-même (car je ne vois pas l'objet de contexte, comme dans l'JMock) et la simulation(et le contexte de l'application) est partagé par les deux méthodes d'essai.
Je l'ai résolu en ajoutant reset() dans la méthode @before. Ma question est quelle est la meilleure pratique pour gérer cette situation (La javadoc de réinitialisation() dit que le code est l'odeur si vous avez besoin de reset())? Toute idée est d'apprécier, merci d'avance.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/booking-servlet.xml",
"classpath:test-booking-servlet.xml" })
@WebAppConfiguration
public class PlaceOrderControllerIntegrationTests implements IntegrationTests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Autowired
private PlaceOrderService placeOrderService;
@Before
public void setup() {
this.mockMvc = webAppContextSetup(this.wac).build();
reset(placeOrderService);//reset mock
}
@Test
public void fowardsToFoodSelectionViewAfterPendingOrderIsPlaced()
throws Exception {
final Address deliveryAddress = new AddressFixture().build();
final String deliveryTime = twoHoursLater();
final PendingOrder pendingOrder = new PendingOrderFixture()
.with(deliveryAddress).at(with(deliveryTime)).build();
when(placeOrderService.placeOrder(deliveryAddress, with(deliveryTime)))
.thenReturn(pendingOrder);
mockMvc.perform(...);
}
@Test
public void returnsToPlaceOrderViewWhenFailsToPlaceOrder() throws Exception {
final Address deliveryAddress = new AddressFixture().build();
final String deliveryTime = twoHoursLater();
final PendingOrder pendingOrder = new PendingOrderFixture()
.with(deliveryAddress).at(with(deliveryTime)).build();
NoAvailableRestaurantException noAvailableRestaurantException = new NoAvailableRestaurantException(
deliveryAddress, with(deliveryTime));
when(placeOrderService.placeOrder(deliveryAddress, with(deliveryTime)))
.thenThrow(noAvailableRestaurantException);
mockMvc.perform(...);
}
source d'informationauteur Hippoom
Vous devez vous connecter pour publier un commentaire.
Sur le placement de la réinitialisation après la méthode de test
Je pense que mettre à zéro les objets fantaisie, devrait être fait après la méthode de test, car il implique qu'il n'y est en effet quelque chose qui s'est passé pendant le test qui doivent être nettoyées.
Si la réinitialisation est effectuée avant la méthode d'essai, j'avais l'impression de doute, ce que le diable qui s'est passé avant le test qui doit être réinitialisée? Qu'en est au sujet de la non-se moque de l'objet? Est-il une raison (peut-être qu'il est)? Si il ya une raison pourquoi il n'est pas mentionné dans le code (par exemple le nom de la méthode)? Et cetera.
Pas un fan de Printemps en fonction des tests
Fond
À l'aide de Printemps est comme l'abandon de l'unité de test d'une classe, avec le Printemps, vous avez moins de contrôle sur le test : isolementinstanciationcycle de viepour ne citer que quelques-uns de la cherché propriété dans un test unitaire. Cependant, dans de nombreux cas, l'offre de Printemps, les bibliothèques et un cadre qui ne sont pas que "transparent", pour les tests vous test mieux le comportement réel de l'ensemble de trucs, comme avec Spring MVC, Spring Batch, etc.
Et de l'élaboration de ces tests est beaucoup plus gênant, car il impose dans de nombreux cas, le développeur de l'artisanat tests d'intégration sérieusement à tester le comportement de la production de code. Comme beaucoup de développeurs ne sais pas tous les détails sur le fonctionnement de votre code de vie à l'intérieur de Printemps, ce qui peut conduire à de nombreuses surprises pour essayer de tester une classe avec des tests unitaires.
Mais la difficulté continue, les tests devraient être rapide, petit et à donner retour rapide pour les développeurs (IDE plugin comme Infinitest sont parfaits pour ça), mais les tests avec le Printemps sont, par nature, plus lente et plus la consommation de mémoire. Ce qui tend à exécuter en moins souvent et même de les éviter totalement sur le poste local, ...à découvrir par la suite sur le serveur CI qu'ils échouent.
Cycle de vie avec Mockito et le Printemps
Ainsi, quand un test d'intégration est conçu pour un sous-système, vous retrouver avec de nombreux objets et évidemment, les collaborateurs, qui sont probablement moqué. Le cycle de vie est contrôlée par le Printemps Coureur, mais Mockito se moque ne le sont pas. Donc, vous avez à gérer l'on se moque de cycle de vie-même.
De nouveau sur le cycle de vie d'un projet avec Spring Batch, nous avons eu quelques problèmes avec les effets résiduels sur la non on se moque de nous avions donc deux choix, faire une seule méthode de test par classe de test ou d'utiliser le sale contexte astuce :
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
. Cela a conduit à un ralentissement de tests, la hausse de la consommation de mémoire, mais c'était la meilleure option que nous avions. Avec cette astuce, vous n'aurez pas à réinitialiser Mockito se moque.Une lumière dans l'obscurité
Je ne connais pas assez bien le projet, mais springockito peut vous fournir un peu de sucre sur le cycle de vie. Le annotation sous-projet semble être encore mieux : il semble laisser de Printemps de gérer le cycle de vie du haricot dans le Printemps récipient et laissez-le test de contrôle de la façon dont se moque de qui sont utilisés. Je n'ai encore aucune expérience avec cet outil, alors il pourrait y avoir des surprises.
Comme un avertissement, j'aime le Printemps beaucoup, il offre de nombreuses remarquable outil pour simplifier autre cadre de l'utilisation, il peut augmenter la productivité, il aide à la conception, mais comme tous les outils, les Humains ont inventé il y a toujours un bord rugueux (si pas plus...).
Sur une note de côté, c'est intéressant de voir ce problème arrive d'être dans un JUnit contexte, comme JUnit instancier la classe de test pour chaque méthode de test. Si le test était basé sur TestNG alors l'approche pourrait être un peu différent que TestNG crée une seule instance de la classe de test, de repos se moquer des champs serait obligatoire quelle que soit l'aide de Printemps.
Vieille réponse:
Je ne suis pas un grand fan de l'utilisation de Mockito se moque, au printemps de conxtext. Mais pourriez-vous être à la recherche de quelque chose comme :
Printemps fonction de test est difficile de faire vite et independed (comme @Brice écrit). Voici un petit utilitaire méthode pour réinitialiser tous les objets fantaisie (il faut l'appeler manuellement dans chaque
@Before
méthode):Comme vous le voyez il y a une itération pour tous les haricots, vérifier si le bean est simulé ou pas, et de réinitialiser la simulation. - Je faire particulièrement attention sur appel
AopUtils.isAopProxy
et((Advised)bean).getTargetSource().getTarget()
. Si vous haricot contient un@Transactional
annotation de la maquette de ce bean toujours enveloppé par du printemps à l'objet proxy, afin de réinitialiser ou de vérifier cette maquette vous devez déballer premier. Autrement, vous obtiendrez uneUnfinishedVerificationException
qui peuvent survenir dans différents tests de temps en temps.Dans mon cas
AopUtils.isAopProxy
est assez. Mais il y a aussiAopUtils.isCglibProxy
etAopUtils.isJdkDynamicProxy
si vous rencontrez des problèmes avec l'utilisation de proxy.mockito est
1.10.19
printemps-test est
3.2.2.RELEASE
Spring Boot
@MockBean
annotation que vous pouvez utiliser pour se moquer de votre service. Vous n'avez pas besoin de réinitialiser se moque manuellement. Il suffit de remplacer@Autowired
par@MockBean
:Au lieu de l'injection de la
placeOrderService
objet, vous devriez probablement juste laisser Mockito l'initialiser comme un@Mock
avant chaque test, par quelque chose comme ceci:Comme recommandé dans la Javadoc ici:
http://docs.mockito.googlecode.com/hg/latest/org/mockito/MockitoAnnotations.html
Vous pouvez même mettre la
@Before
méthode dans une super-classe et juste de le proroger pour chaque classe de cas de test qui utilise@Mock
objets.