Weld JUnit 4 Runner

I’ve been having a look at Weld recently and wanted to be able to try some stuff out without a container in JUnit, but couldn’t find a JUnit Runner class to do it for me.

I was really suprised how simple it was:

package org.objectopia.test;

import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

public class WeldJUnit4Runner extends BlockJUnit4ClassRunner {

    private final Class klass;
    private final Weld weld;
    private final WeldContainer container;

    public WeldJUnit4Runner(final Class klass) throws InitializationError {
        super(klass);
        this.klass = klass;
        this.weld = new Weld();
        this.container = weld.initialize();
    }

    @Override
    protected Object createTest() throws Exception {
        final Object test = container.instance().select(klass).get();

        return test;
    }
}

Now you can do this :

@RunWith(WeldJUnit4Runner.class)
public class PersistenceTest {

    @Inject UserRepository repository;

    ...
}

Because your test class is just another CDI bean, you can inject any bean reference you require.

This is where the power of CDI comes in to play, you can do something like this:

    @Inject @Mock UserRepository userRepository;

And create a producer method to mock it out:

    @Produces @Mock UserRepository createUserRepository() { ... }
Advertisements

4 thoughts on “Weld JUnit 4 Runner

  1. Thanks for that post! One question – I have simple maven JavaSE project which only prints Hello World on the console via an inject. When executed inside eclipse with a run configuration in which I specify the main class org.jboss.weld.environment.se.StartMain the program works just fine. However, when I executed a “mvn compile test” it fails. Why? I use the exec-maven-plugin to specify the mainClass for phase test/goal java.

    Running asd.MainTest
    23 [main] INFO org.jboss.weld.Version – WELD-000900 1.1.10 (Final)
    114 [main] INFO org.jboss.weld.Bootstrap – WELD-000101 Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
    348 [main] WARN org.jboss.weld.interceptor.util.InterceptionTypeRegistry – Class ‘javax.ejb.PostActivate’ not found, interception based on it is not enabled
    349 [main] WARN org.jboss.weld.interceptor.util.InterceptionTypeRegistry – Class ‘javax.ejb.PrePassivate’ not found, interception based on it is not enabled
    Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.541 sec <<< FAILURE!

    Results :

    Tests in error:
    initializationError(asd.MainTest): Index: 0, Size: 0

  2. Or you could use Weld + its Arquillian container.
    A bit more work wrt jars + classpath,
    but you could then easily pass the same test around between diff containers.

      • It’s just a matter of adding the right (additional) deps to the classpath.
        Wrt the test, it’s pretty much the same, WeldJUnit4Runner –> Arquillian.
        While then you can properly test your stuff, not just in mock-ed up embedded Weld container,
        but real runtime env; JBossAS, GF, Tomcat, Jetty, … all with exactly the same code.

        But that doesn’t mean I don’t like how you did it, as it nicely shows true power of JUnit and CDI. šŸ™‚

Comments are closed.