2010-08-03 12 views
0

A notre avis, nous avons une couche de service qui prend en charge une requête XML, accède à diverses procédures stockées (SP) via JDBC, traite les données et répond avec une réponse XML. Dernièrement, les gens ont commencé à adopter MockRunner dans leurs tests JUnit pour se moquer des réponses des SP.Pourquoi est-ce que j'utiliserais MockRunner plutôt qu'une injection de dépendances normale/manuelle?

MockConnection connection = new MockConnection(); 
    MockContextFactory.setAsInitial(); 
    InitialContext context = new InitialContext(); 
    context.rebind(READ_PAYMENT_DATA_SOURCE, getDS()); 
    getDS().setupConnection(connection); 
    m_csStatementHandler = connection.getCallableStatementResultSetHandler(); 
    m_csStatementHandler.clearResultSets(); 
    m_csStatementHandler.clearCallableStatements(); 
    m_csStatementHandler.setExactMatch(false); 
m_csStatementHandler.prepareReturnsResultSet(READ_PAYMENT, true); 
    m_csStatementHandler.setExactMatch(false); 
    m_csStatementHandler.setExactMatchParameter(false); 
    Map parameterMap = new HashMap(); 
    parameterMap.put(new Integer(1), null); 
    parameterMap.put(new Integer(2), null); 
    parameterMap.put(new Integer(3), null); 
    parameterMap.put(new Integer(4), null); 
    m_csStatementHandler.prepareOutParameter(READ_PAYMENT, parameterMap); 
    //Set up the cursor of applications for return. 
    MockResultSet resultApps = m_csStatementHandler.createResultSet(); 

    resultApps.addRow(getPaymentSchedule("E", "Monthly", new Short("1"),null,null,null,null,null,null,null)); 
    resultApps.addRow(getPaymentSchedule("A", "Weekly", new Short("1"),null,null,null,null,null,null,null)); 
    resultApps.addRow(getPaymentSchedule("R", "Yearly", new Short("1"),null,null,null,null,null,null,null)); 
    resultApps.addRow(getPaymentSchedule("S", "Weekly", new Short("1"),null,null,null,null,null,null,null)); 
    resultApps.addRow(getPaymentSchedule("W", "Monthly", new Short("1"),null,null,null,null,null,null,null)); 

    MockResultSet[] results = new MockResultSet[1]; 
    results[0] = resultApps; 
    m_csStatementHandler.prepareResultSet(READ_PAYMENT, resultApps); 

Le code ci-dessus est terrible pour de nombreuses raisons, mais il ne montre clairement la complexité et: le code pour configurer les réponses de l'SP raillé à l'aide MockRunner est horrible (ce qui est la première classe de test aléatoire j'ai ouvert) surcharge de la configuration d'une réponse à partir des procédures stockées. À ce jour, j'ai utilisé l'injection de dépendance roulée à la main pour injecter la classe qui appelle réellement la procédure stockée. Tout ce que j'ai à faire est de créer une classe d'appel simulateur SP (responsable de l'exécution réelle du SP) et définir mes données de réponse souhaitées. Je suis très heureux avec cette technique et son beaucoup plus simple que ce qui précède que ses données se concentrent plutôt que de se soucier des détails de mise en œuvre. Mais ma question est, quand voudriez-vous utiliser MockRunner? Cela semble exagéré pour les tests unitaires, alors je suppose que c'est plus pour l'intégration ou le test du système? Et même alors, il me semble encore plus facile d'utiliser un cadre DI pour échanger la classe de l'appelant SP puis pour installer tout le code ci-dessus pour chaque appel de procédure stockée. S'il vous plaît éclairer! Merci

Répondre

2

En fin de compte, vous vous penchez sur la philosophie derrière la moquerie en général. Je vais vous donner mes deux cents, mais je voudrais aussi vous référer à n'importe quelle grande bibliothèque moqueuse, qui est susceptible de fournir une bonne justification de leur propre existence. Prenez Mockito, par exemple. La communauté testing/Mocking fait souvent la distinction entre ce que l'on roule à la main, ce qu'on appelle habituellement un «stub» (une classe statique, écrite à la main) et un «mock» (une classe dynamique générée par l'exécution).).

Les avantages de la simulation sont assez importants par rapport à la simple réduction. De nombreux testeurs s'irritent à l'idée de partir écrire des implémentations d'interfaces et/ou de classes de sous-classes concrètes juste à des fins de test. Pour ce faire, il faut souvent implémenter TOUTES les méthodes de cette classe/interface, même si vous voulez simplement tester une méthode spécifique. Mocking vous permet de contourner ce problème en définissant seulement les méthodes auxquelles vous voulez donner un comportement, et c'est puissant. De plus, le fait de se moquer vous permet de changer de comportement d'un test à l'autre. Pour faire cela avec stubbing, vous devez écrire une toute nouvelle classe stub.

La syntaxe varie un peu entre la bibliothèque de simulation et la bibliothèque. Certains peuvent être plus lisibles que d'autres. Mon préféré actuel est Mockito, d'où la référence précédente, mais ils évoluent au fil du temps. Il pourrait être utile de déterminer pourquoi votre organisation utilise la suite moqueuse qu'elle est et si une autre pourrait encore répondre à vos besoins tout en étant plus lisible.

Espérons que vos rédacteurs de test tirent un comportement commun dans les méthodes d'installation de test (comme @Before de JUnit) afin que vous n'ayez pas besoin de voir la création simulée et l'initialisation commune partout.

+0

Merci pour votre inscription. Je connais Mockito que j'aime beaucoup. –