54 votes

Redéfinition des haricots de printemps dans l'environnement de test unitaire

nous sommes à l'aide de Printemps pour mon application, de Printemps et d'Essais pour les tests unitaires. Nous avons un petit problème cependant: le code de l'application charge un Printemps contexte de l'application à partir d'une liste d'emplacements (fichiers xml) dans le classpath. Mais lorsque nous effectuons nos tests unitaires, nous avons envie de voir le Printemps des grains à se moque plutôt qu'à part entière de la mise en œuvre des classes. En outre, pour certains tests unitaires nous voulons des haricots pour devenir se moque, alors que pour les autres tests unitaires nous voulons autres haricots pour devenir se moque, comme nous testons les différentes couches de l'application.

Tout cela pour dire que je veux redéfinir spécifiques haricots du contexte de l'application et l'actualisation du cadre lorsque vous le souhaitez. En faisant cela, je veux redéfinir une petite partie seulement des haricots situé dans l'un (ou plusieurs) xml d'origine haricots fichier de définition. Je ne peux pas trouver un moyen facile de le faire. Il est toujours considéré que le Printemps est un test unitaire cadre convivial donc, quelque chose doit m'échapper d'ici.

Avez-vous des idées de comment le faire?

Merci.

18voto

Michael Pralow Points 3315

Je proposerais un TestClass personnalisé et quelques règles simples pour les emplacements du bean printanier.xml

 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath*:spring/*.xml",
"classpath*:spring/persistence/*.xml",
"classpath*:spring/mock/*.xml"})
@Transactional
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DirtiesContextTestExecutionListener.class})

public abstract class AbstractHibernateTests implements ApplicationContextAware {

/**
 * Logger for Subclasses.
 */
protected final Logger LOG = LoggerFactory.getLogger(getClass());
/**
 * The {@link ApplicationContext} that was injected into this test instance
 * via {@link #setApplicationContext(ApplicationContext)}.
 */
protected ApplicationContext applicationContext;

/**
 * Set the {@link ApplicationContext} to be used by this test instance,
 * provided via {@link ApplicationContextAware} semantics.
 */
@Override
public final void setApplicationContext(
        final ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
}
 

}

s'il y a mock-bean.xml à l'emplacement spécifié, ils remplaceront tous les "vrais" bean.xml des emplacements "normaux" - vos emplacements normaux peuvent être différents

mais ... je ne mélangerais jamais des haricots fictifs et non fictifs, il est difficile de déceler les problèmes lorsque l'application vieillit

16voto

krosenvold Points 35979

L'une des raisons de printemps est décrit comme test de l'environnement est parce qu'il peut être facile de simplement de nouvelles ou des trucs dans le test de l'unité.

Alternativement, nous avons utilisé la configuration suivante avec un grand succès, et je pense que c'est assez proche de ce que tu veux, je voudrais vivement recommande:

Pour tous les haricots qui ont besoin de différentes mises en œuvre dans des contextes différents, passer à l'annotation en fonction de câblage. Vous pouvez laisser les autres-est.

Mettre en œuvre l'ensemble des annotations

 <context:component-scan base-package="com.foobar">
     <context:include-filter type="annotation" expression="com.foobar.annotations.StubRepository"/>
     <context:include-filter type="annotation" expression="com.foobar.annotations.TestScopedComponent"/>
     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
 </context:component-scan>

Ensuite, vous annoter votre live implémentations avec @Référentiel, votre talon implémentations avec @StubRepository, tout le code qui doit être présent dans l'unité de montage d'essai UNIQUEMENT avec @TestScopedComponent. Vous pouvez exécuter dans un besoin d'un couple de plus annotations, mais ceux-ci sont un excellent point de départ.

Si vous avez beaucoup de spring.xml, vous aurez probablement besoin de faire un peu de nouvelles du printemps des fichiers xml que, fondamentalement, ne contiennent que de la composante-analyse des définitions. Normalement vous devriez simplement ajouter ces fichiers à votre régulière @ContextConfiguration liste. La raison pour cela est parce que vous finissent souvent avec des configurations différentes du contexte-analyse (faites-moi confiance, vous permettra d' en faire au moins 1 de plus annotations si vous êtes en train de faire du web-tests, ce qui rend pour 4 des combinaisons pertinentes)

Puis, fondamentalement, vous utilisez le

@ContextConfiguration(locations = { "classpath:/path/to/root-config.xml" })
@RunWith(SpringJUnit4ClassRunner.class)

Notez que ce programme d'installation ne pas vous permettre d'avoir une alternance de combinaisons de stub/données en direct. Nous avons essayé cela, et je pense que cela a entraîné un désordre, je ne recommanderais pas à personne ;) Nous fil inn l'ensemble de talons ou de l'ensemble des services live.

Nous utilisons principalement l'auto-filaire stub de dépendances lors de l'essai de gui près de trucs où les dépendances sont généralement tout à fait substantiels. En nettoyant le code que nous utilisons de plus en plus réguliers de tests unitaires.

Dans notre système, nous avons les éléments suivants de fichiers xml pour la composante d'analyse:

  • régulière de la production web
  • pour le démarrage de web avec des talons de seulement
  • pour les tests d'intégration (dans junit)
  • pour les tests unitaires (en junit)
  • pour le sélénium tests web (dans junit)

Cela signifie que nous avons totalement d'avoir 5 différents à l'échelle du système des configurations que l'on peut démarrer l'application avec. Puisque nous utilisons seulement les annotations, le printemps est assez rapide pour autowire même ceux des tests unitaires nous voulons filaire. Je sais que c'est original, mais c'est vraiment génial.

De l'intégration les tests s'exécutent avec le live complet de l'installation, et une fois ou deux fois j'ai décidé de vraiment pragmatique et qui veulent avoir une 5 live câblages et une seule maquette:

public class HybridTest {
   @Autowired
   MyTestSubject myTestSubject;


   @Test
   public void testWith5LiveServicesAndOneMock(){
     MyServiceLive service = myTestSubject.getMyService();
     try {
          MyService mock = EasyMock.create(...)
          myTestSubject.setMyService( mock);

           .. do funky test  with lots of live but one mock object

     } finally {
          myTestSubject.setMyService( service);
     }


   }
}

Je sais que le test puristes vont être tous sur moi pour cela. Mais parfois, c'est juste un de très pragmatique solution qui s'avère être très élégant lorsque l'alternative serait vraiment vraiment moche. De nouveau, c'est généralement dans ces gui-à proximité de zones.

7voto

Ev0oD Points 100

Voir ce tutoriel avec l'annotation @InjectedMock

Cela m'a fait gagner beaucoup de temps. Vous venez d'utiliser

 @Mock
SomeClass mockedSomeClass

@InjectMock
ClassUsingSomeClass service

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}
 

et tous vos problèmes sont résolus. Mockito remplacera l'injection de dépendance de printemps par une maquette. Je viens de l'utiliser moi-même et cela fonctionne très bien.

6voto

Daniel Alexiuc Points 2304

Certaines solutions très complexes et puissantes sont énumérées ici.

Mais il existe un moyen plus simple, FAR, FAR , pour accomplir ce que Stas a demandé, qui ne consiste pas à modifier autre chose qu'une ligne de code dans la méthode de test. Cela fonctionne aussi bien pour les tests unitaires que pour les tests d'intégration Spring, pour les dépendances câblées automatiquement, les champs privés et protégés.

C'est ici:

 junitx.util.PrivateAccessor.setField(testSubject, "fieldName", mockObject);
 

4voto

toolkit Points 27248

Vous pouvez également écrire vos tests unitaires nécessite pas de recherches à tous:

@ContextConfiguration(locations = { "classpath:/path/to/test-config.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class MyBeanTest {

    @Autowired
    private MyBean myBean; // the component under test

    @Test
    public void testMyBean() {
        ...
    }
}

Cela donne un moyen facile de mélanger et match du real fichiers de configuration de test avec des fichiers de configuration.

Par exemple, lors de l'utilisation d'hibernate, je peux avoir mes sessionFactory bean dans un fichier de configuration (pour être utilisé dans les tests et l'application principale), et ont par la source de données de haricot dans un autre fichier de configuration (on peut utiliser un DriverManagerDataSource à un en mémoire db, l'autre pourrait utiliser JNDI-recherche).

Mais, certainement en tenir compte de @cletus l' avertissement ;-)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X