Dans mon billet précédent, j’ai proposé d’utiliser un Rule pour tester des composants CDI. Cette technique n’est pas totalement satisfaisante, d’une part parce que l’initialisation se fait pour chaque test et d’autre part parce que son utilisation demande un peu de code. J’ai donc décidé de changer de tactique et développer un Runner.

Pour ce Runner, j’ai fait une classe qui hérite du runner par défaut et j’ai redéfini la méthode run() pour démarrer et arrêter Weld. J’ai redéfini aussi la méthode createTest() afin qu’elle retourne une instance gérée par Weld de la classe de test. Ceci permet d’injecter les objets à tester et donc de réduire sensiblement la quantité de code.

public class WeldRunner extends BlockJUnit4ClassRunner {

    private Weld weld;
    private WeldContainer container;

    public WeldRunner(Class klass) throws InitializationError {
        super(klass);
    }

    @Override
    public void run(RunNotifier notifier) {
        initializeWeld();
        super.run(notifier);
        shutdownWeld();
    }

    @Override
    protected Object createTest() throws Exception {
        return container
                   .instance()
                   .select(getTestClass().getJavaClass())
                   .get();
    }

    private void initializeWeld() {
        weld = new Weld();
        container = weld.initialize();
    }

    private void shutdownWeld() {
        weld.shutdown();
    }
}

Il ne reste plus qu’à l’utiliser et à injecter le beans à tester.

@RunWith(WeldRunner.class)
public class TotoServiceTest3 {

    @Inject
    TotoService service;

    ...
}

Je trouve cette technique plus sympa que la Rule, il reste à la tester plus sérieusement. J’ai ajouté ce Runner à ma synthèse des techniques de tests CDI, sur JTips.