web-dev-qa-db-fra.com

Comment exécuter JUnit SpringJUnit4ClassRunner avec Parameterized?

Le code suivant n'est pas valide en raison d'une annotation @RunWith en double:

@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(Parameterized.class)
@SpringApplicationConfiguration(classes = {ApplicationConfigTest.class})
public class ServiceTest {
}

Mais comment puis-je utiliser ces deux annotations conjointement?

57
membersound

Il y a au moins 2 options pour le faire:

  1. Après http://www.blog.project13.pl/index.php/coding/1077/runwith-junit4-with-both-springjunit4classrunner-and-parameterized/

    Votre test doit ressembler à ceci:

     @RunWith(Parameterized.class)
     @ContextConfiguration(classes = {ApplicationConfigTest.class})
     public class ServiceTest {
    
         private TestContextManager testContextManager;
    
         @Before
         public void setUpContext() throws Exception {
             //this is where the magic happens, we actually do "by hand" what the spring runner would do for us,
            // read the JavaDoc for the class bellow to know exactly what it does, the method names are quite accurate though
           this.testContextManager = new TestContextManager(getClass());
           this.testContextManager.prepareTestInstance(this);
         }
         ...
     }
    
  2. Il existe un projet github https://github.com/mmichaelis/spring-aware-rule , qui repose sur le blog précédent, mais ajoute le support de manière générale.

    @SuppressWarnings("InstanceMethodNamingConvention")
    @ContextConfiguration(classes = {ServiceTest.class})
    public class SpringAwareTest {
    
        @ClassRule
        public static final SpringAware SPRING_AWARE = SpringAware.forClass(SpringAwareTest.class);
    
        @Rule
        public TestRule springAwareMethod = SPRING_AWARE.forInstance(this);
    
        @Rule
        public TestName testName = new TestName();
    
        ...
    }
    

Ainsi, vous pouvez avoir une classe de base implémentant l’une des approches et tous les tests qui en héritent.

34
mavarazy

Vous pouvez utiliser SpringClassRule et SpringMethodRule - fournies avec Spring

import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;

@RunWith(Parameterized.class)
@ContextConfiguration(...)
public class MyTest {

    @ClassRule
    public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();

    @Rule
    public final SpringMethodRule springMethodRule = new SpringMethodRule();

    ...
70
keyoxy

Il existe une autre solution avec JUnit 4.12 sans la nécessité de Spring 4.2+.

JUnit 4.12 introduit ParametersRunnerFactory qui permet de combiner test paramétré et injection Spring.

public class SpringParametersRunnerFactory implements ParametersRunnerFactory {
@Override
  public Runner createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
    final BlockJUnit4ClassRunnerWithParameters runnerWithParameters = new BlockJUnit4ClassRunnerWithParameters(test);
    return new SpringJUnit4ClassRunner(test.getTestClass().getJavaClass()) {
      @Override
      protected Object createTest() throws Exception {
        final Object testInstance = runnerWithParameters.createTest();
        getTestContextManager().prepareTestInstance(testInstance);
        return testInstance;
      }
    };
  }
}

L'usine peut être ajoutée à la classe de test pour fournir un support Spring complet tel que transaction de test , réinitie le contexte sale et test de servlet .

@UseParametersRunnerFactory(SpringParametersRunnerFactory.class)
@RunWith(Parameterized.class)
@ContextConfiguration(locations = {"/test-context.xml", "/mvc-context.xml"})
@WebAppConfiguration
@Transactional
@TransactionConfiguration
public class MyTransactionalTest {

  @Autowired
  private WebApplicationContext context;

  ...
}

Si vous avez besoin du contexte Spring dans @Parameters static pour fournir les paramètres permettant de tester les instances, veuillez consulter ma réponse ici Comment utiliser le programme de test JUnit paramétré avec un champ injecté avec Spring? .

1
Arnor

Gérez vous-même le contexte de l'application

Ce qui a fonctionné pour moi, c’est de disposer d’une classe de test @RunWith(Parameterized.class) qui gère le contexte de l’application "à la main".

Pour ce faire, j'ai créé un contexte d'application avec la même collection de chaînes que dans le @ContextConfiguration. Donc au lieu d'avoir

@ContextConfiguration(locations = { "classpath:spring-config-file1.xml",
    "classpath:spring-config-file2.xml" })

J'ai eu

ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {
            "classpath:spring-config-file1.xml", "classpath:spring-config-file2.xml"  });

Et pour chaque @Autowired dont j'avais besoin, je l'ai récupéré à la main dans le contexte créé:

SomeClass someBean = ctx.getBean("someClassAutowiredBean", SomeClass.class);

N'oubliez pas de fermer le contexte à la fin:

((ClassPathXmlApplicationContext) ctx).close();
0
manuelvigarcia