2010-03-17 18 views
0

Voir le test de simulation suivante en utilisant Spring/Spring MVCMock versus implémentation. Comment partager les deux approches dans une seule classe de test?

public class OrderTest { 

    // SimpleFormController 
    private OrderController controller; 
    private OrderService service; 

    private MockHttpServletRequest request; 

    @BeforeMethod 
    public void setUp() { 

     request = new MockHttpServletRequest(); 
     request.setMethod("POST"); 

     Integer orderNumber = 421; 
     Order order = new Order(orderNumber); 

     // Set up a Mock service 
     service = createMock(OrderService.class); 
     service.save(order); 

     replay(service); 

     controller = new OrderController(); 
     controller.setService(service); 
     controller.setValidator(new OrderValidator()); 

     request.addParameter("orderNumber", String.valueOf(orderNumber)); 
    } 

    @Test 
    public void successSave() { 
     controller.handleRequest(request, new MockHttpServletResponse()); 

     // Our OrderService has been called by our controller 
     verify(service); 
    } 

    @Test 
    public void failureSave() { 
     // Ops... our orderNumber is required 
     request.removeAllParameters(); 

     ModelAndView mav = controller.handleRequest(request, new MockHttpServletResponse()); 

     BindingResult bindException = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + "command"); 

     assertEquals("Our Validator has thrown one FieldError", bindException.getAllErrors(), 1); 
    } 

} 

Comme vous pouvez le voir, je fais comme proposé par Triple A pattern

  • Arrangement (méthode setUp)
  • Loi (contrôleur. handleRequest)
  • assert (vérifier et assertEquals)

Mais je voudrais tester à la fois Mock et la classe d'implémentation (OrderService) en utilisant cette seule classe de test. Ainsi, afin de récupérer ma mise en œuvre, je re-écrire ma classe comme suit

@ContextConfiguration(locations="/app.xml") 
public class OrderTest extends AbstractTestNGSpringContextTests { 



} 

Alors, comment dois-je écrire mon seul test à Réorganiser à la fois OrderService Mock et mise en œuvre sans changer ma méthode de test (sucessSave et failureSave)

J'utilise TestNG, mais vous pouvez montrer à JUnit si vous voulez

salutations

Répondre

1

Encore une fois pour moi, il ressemble à deux tests différents, mais si vous allez être catégorique :) ici il est

@SpringJunit4Runner(....="app.xml") 
public class OrderTest { 

    @Resource 
    private OrderController controller; //bean from app.xml 

    @Resource 
    private OrderService service; // actual order service 
    private OrderService mockOrderService; //some mock order service 
    private MockHttpServletRequest request; 

    @BeforeMethod 
    public void setUp() { 
     request = new MockHttpServletRequest(); 
     request.addParameter("orderNumber", String.valueOf(orderNumber)); 
    } 

    @Test 
    public void successSave() { 
     //test with orderService the way you would do it 
    } 

    @Test 
    @DirtiesContext 
    //need the annotation because we are changing our context beans i.e, ordercontroller 
    //so for the next test the context would be recreated 
    public void successSaveWithMock() { 
     mockOrderService = //create mock service 
     orderController.setOrderService(mockOrderService); 
     //do the test with mock 
    } 
} 

Ceci est pour junit4 mais pour votre TestNG il devrait être le principe même/similaire. Encore une fois je suppose que vous avez fait votre recherche sur pourquoi vous avez besoin d'un test unitaire et un test d'intégration dans le même fichier !!!

+0

@Calm Storm Merci. Je sais que j'ai un test d'unité et d'intégration selon ma question. Mais il se passe que j'ai beaucoup de request.addParameter dans la méthode setUp. Pour cette raison, je voudrais utiliser à la fois les tests unitaires et d'intégration dans une seule classe de test. Mais, en suivant de bons modèles, où devrais-je mettre mon setUp methd (beaucoup de request.addParameter) ** afin de séparer dans différentes classes ** à la fois Unit et Interaction Testing ??? Pouvez-vous montrer dans le code ??? –

+0

Cela dépend vraiment du problème. Dans votre cas, je vais avoir à la place de la ligne request.addParamter, j'aurais HelperUtil.setUpParams (request) qui va remplir certaines valeurs de commande dans la requête et ensuite vous renvoyer orderNumber. –

+0

Merci, bon à savoir –

1

Pour moi, ces serait deux tests distincts (ou ensembles de tests, pour être précis). Je dirais que tester OrderController est différent de tester OrderService, même s'il y a des éléments similaires dans la configuration de test pour les deux. Les tests unitaires évaluent des tests simples qui testent une chose (un cas d'utilisation avec un objet) à la fois, et à mon humble avis pour une bonne raison. Chaque classe a son propre contrat d'interface, avec ses propres conditions aux limites, qui doivent être testées séparément.

En outre, il est tout simplement difficile d'essayer de tester OrderService via le contrôleur, au lieu de l'appeler directement dans vos méthodes de test. Il est probable que lorsque vous appelez via un contrôleur, vous n'aurez pas autant de liberté pour passer des paramètres "complexes" à l'exercice des conditions aux limites.

Je recommande donc d'écrire deux classes de test distinctes, en mettant l'accent sur le fait de tester sa propre classe. Ensuite, une fois que vous êtes satisfait de vos tests unitaires et que vous n'avez plus d'idées sur ce qu'il faut tester, vous pouvez consulter les méthodes d'installation et d'assistance pour voir si vous pouvez supprimer une duplication avec un peu de refactoring. Mais pour moi, ce n'est pas une préoccupation majeure d'enregistrer quelques lignes de code dans mes classes de test. Le point principal est de tester tout ce qui pourrait éventuellement se casser, et de garder les tests simples, pour bien comprendre ce que ce test est en train de tester. Essayer de tester deux objets à la fois rend définitivement vos tests plus difficiles à comprendre (et donc à maintenir, à long terme).

2

Ce sont des types de test très différents. Le premier est un test unitaire type testant l'unité de contrôle. Le second est un petit test d'intégration testant l'interaction entre le contrôleur et le service et la configuration du ressort.

Alors ne remplacez pas le premier test par le second, c'est un supplémentaire!