用DbUnit实现Dao层的单元测试中,我把数据库scheme脚本放在了/src/test/resources目录下,这样在初始化dataSource的时候,可以很方便地初始化数据库:

1
2
3
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
  <jdbc:script location="classpath:scheme.sql"/>
</jdbc:initialize-database>

但是scheme.sql放在/src/test/resources下其实不太合理,数据库的scheme脚本应该是project级别的,不应该放在test下。而放在/src/main/resources下感觉也不太合理,/src/main/resources下放置的内容应该是在运行时会用到的各种配置文件。

参考what’s the recommened location for sql ddl scripts,我把scheme.sql移到了/src/main/db。对应地,在单元测试初始化数据库的时候,script location就不能用classpath来定位了。把spring配置修改一下,以${project.basedir}开始,定位ddl脚本。

1
2
3
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
  <jdbc:script location="file:///${project.basedir}/src/main/db/scheme.sql"/>
</jdbc:initialize-database>

再次执行测试,失败了。Cannot resolve ${project.basedir}。${project.basedir}是maven的变量,Spring是无法直接读取的。但是可以通过properties文件来传递。具体的步骤如下:

  1. 为测试创建一个/src/test/resources/test-env.properties文件。
1
project.basedir = ${project.basedir}
  1. 在pom里配置对test-env.properties文件使用filter。这样在maven处理test resources的时候,会把${project.basedir}替换为变量值。
1
2
3
4
5
6
<build>
  <testResource>
    <directory>src/test/resources</directory>
    <filtering>true</filtering>
  </testResource>
</build>
  1. 在Spring配置文件中引用test-env.properties,然后使用project.basedir属性定位scheme文件。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
    <array>
      <value>classpath:test-env.properties</value>
    </array>
  </property>
</bean>

<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
  <jdbc:script location="file:///${project.basedir}/src/main/db/scheme.sql"/>
</jdbc:initialize-database>

重新执行测试,顺利通过。