Spring Transactional Parameterized Test and Autowiring

Is there a way to get a class that extends AbstractTransactionalJUnit4SpringContexts to play nicely with JUnit's own @RunWith(Parameterized.class), so that fields marked as Autowired get wired in properly?

@RunWith(Parameterized.class)
public class Foo extends AbstractTransactionalJUnit4SpringContextTests {

    @Autowired private Bar bar

    @Parameters public static Collection<Object[]> data() {
        // return parameters, following pattern in
        // http://junit.org/apidocs/org/junit/runners/Parameterized.html
    }

    @Test public void someTest(){
        bar.baz() //NullPointerException
    }
}

Answers


See http://jira.springframework.org/browse/SPR-5292 There is a solution.


You can use a TestContextManager from Spring. In this example, I'm using Theories instead of Parameterized.

@RunWith(Theories.class)
@ContextConfiguration(locations = "classpath:/spring-context.xml")
public class SeleniumCase {
  @DataPoints
  public static WebDriver[] drivers() {
    return new WebDriver[] { firefoxDriver, internetExplorerDriver };
  }

  private TestContextManager testContextManager;

  @Autowired
  SomethingDao dao;

  private static FirefoxDriver firefoxDriver = new FirefoxDriver();
  private static InternetExplorerDriver internetExplorerDriver = new InternetExplorerDriver();

  @AfterClass
  public static void tearDown() {
    firefoxDriver.close();
    internetExplorerDriver.close();
  }

  @Before
  public void setUpStringContext() throws Exception {
    testContextManager = new TestContextManager(getClass());
    testContextManager.prepareTestInstance(this);
  }

  @Theory
  public void testWork(WebDriver driver) {
    assertNotNull(driver);
    assertNotNull(dao);
  }
}

I found this solution here : How to do Parameterized/Theories tests with Spring


No, you can't. The superclass has:

@RunWith(SpringJUnit4ClassRunner.class)

which assures that the tests are run within spring context. If you replace it, you are losing this.

What comes to my mind as an alternative is to extend SpringJunit4ClassRunner, provide your custom functionality there and use it with @RunWith(..). Thus you will have the spring context + your additional functionality. It will call super.createTest(..) and then perform additional stuff on the test.


Inspired by Simon's solution, you can use TestContextManager also with Parameterized runner:

@RunWith(Parameterized.class)
@ContextConfiguration(locations = "classpath:/spring-context.xml")
public class MyTestClass {

  @Parameters public static Collection data() {
    // return parameters, following pattern in
    // http://junit.org/apidocs/org/junit/runners/Parameterized.html
  }

  @Before
  public void setUp() throws Exception {
    new TestContextManager(getClass()).prepareTestInstance(this);
  }

}

Here is full example

I am not sure about handling @Transactional in this case.


I've had to handle the transactions programmatically (see http://www.javathinking.com/2011/09/junit-parameterized-test-with-spring-autowiring-and-transactions/):

@RunWith(Parameterized.class)
@ContextConfiguration(locations = "classpath*:/testContext.xml")
public class MyTest {

    @Autowired
    PlatformTransactionManager transactionManager;

    private TestContextManager testContextManager;

    public MyTest (... parameters for test) {
        // store parameters in instance variables
    }

    @Before
    public void setUpSpringContext() throws Exception {
        testContextManager = new TestContextManager(getClass());
        testContextManager.prepareTestInstance(this);
    }

    @Parameterized.Parameters
    public static Collection<Object[]> generateData() throws Exception {
        ArrayList list = new ArrayList();
        // add data for each test here
        return list;
    }

    @Test
    public void validDataShouldLoadFully() throws Exception {
        new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
            public Object doInTransaction(TransactionStatus status) {
                status.setRollbackOnly();
                try {
                    ... do cool stuff here

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            }
        });

    }

You can use SpringClassRule and SpringMethodRule for this purpose

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

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

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

    @Autowired 
    private Bar bar

    @Parameters 
    public static Collection<Object[]> data() {
        // return parameters, following pattern in
        // http://junit.org/apidocs/org/junit/runners/Parameterized.html
    }

    @Test 
    public void someTest() {
        bar.baz() //NullPointerException
    }
}

Need Your Help

lifecycle of an azure website

asp.net iis azure web

I want to know lifecycle of Azure Websites – specifically:

have mysql select statement return fully qualified column names like table.field

sql mysql

is there a way to have a mysql select statement return fully qualified column names like "table.field" without using AS for every single field?