我正在尝试学习如何在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());
}
}
答案 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;
然后您可以直接使用该变量。