事务教程 - 测试回滚

时间:2014-05-13 14:59:31

标签: java spring transactions dao jdbctemplate

我正在尝试学习如何在java spring中使用事务。我是一个java新手所以请耐心等待:-)我试图在下面尝试实现的单元测试是测试: 如果抛出运行时异常,则回滚。

我遇到的问题是 显示java.lang.NullPointerException?

好的,这就是..我已经删除了一些代码以帮助提高可读性

TutorialTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class TutorialTest {

    @Autowired
    private Dao dao;


    @Test
    public void that_if_a_runtime_exception_is_thrown_transaction_rolledback(){

        User u = new User();
        u.setUsername("FAIL_TEST");
        u.setPhone("0161");
        u.setEmail("FAIL_TEST@gmail.com");
        //dao.addUser(u);  // -- this will insert if uncommented out so I know it works

        OuterService os  = new OuterService();
        os.addUserThrowError(u);

    }
}

OuterService.java

@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class OuterService {

    @Autowired
    private Dao dao;

    @Transactional
    public void addUserThrowError(User user) throws RuntimeException{

        dao.addUser(user);  // gives me a java.lang.NullPointerException?

        throw new RuntimeException("This should roll back DB entry");
    }

}

豆在

中声明

AppConfig.java

@Configuration
@EnableTransactionManagement
@ComponentScan(value = {"com.training.spring.tx.tutorial.dao",
                        "com.training.spring.tx.tutorial.service"})
public class AppConfig {

    public DataSource dataSource() {

        // Create a BasicDataSource object and configure database

        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost/spring_training_tx");
        dataSource.setUsername("training");
        dataSource.setPassword("training");

        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(){
        return new JdbcTemplate(transactionManager().getDataSource());
    }

}

1 个答案:

答案 0 :(得分:1)

首先,引用javadoc of @ContextConfiguration

  

@ContextConfiguration定义用于的类级元数据   确定如何加载和配置ApplicationContext   集成测试。

考虑如何在OuterService上使用它。看起来好吗? OuterService是否意味着用于加载和配置ApplicationCOntext进行集成测试?除非我遗漏了一些必要的东西,否则答案是:否。

那么OuterService是什么?这是一种服务。你好像想把它当作一个bean。什么是豆? bean是一个对象,其生命周期由Spring管理。这包括bean类的实例化,对象的初始化,后期处理,以及最后的对象的破坏。

如果您创建了这样的对象

OuterService os  = new OuterService();
然后春天没有参与。你创建了这个对象,Spring没有办法加入它。因此,你不能指望Spring自动装配它的领域

@Autowired
private Dao dao;

由于您尚未初始化该字段,因此它仍为null,从而导致NullPointerException

那么我们如何获得一个OuterService bean,其中由Spring管理?您可以为@Bean声明OuterService方法,或者使用OuterService或其任何特化来注释@Component并对其所在的组件进行组件扫描。然后注入bean进入任何其他使用它的bean。例如,

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class TutorialTest {

    @Autowired
    private Dao dao;

    @Autowired
    private OuterService os;

然后您可以直接使用该变量。