Spring:单元和集成测试

我正在寻找使用Spring设置单元和集成测试的最佳实践。

我通常使用3种测试:

  • “真正的”unit testing(没有依赖)
  • 测试作为“单元”测试(内存数据库,本地调用,模拟对象,……)或集成测试(持久数据库,远程调用,……)运行
  • 测试仅作为集成测试运行

目前我只有第二类测试,这是棘手的部分。 我设置了一个基础测试类,如:

@ContextConfiguration(locations = { "/my_spring_test.xml" }) public abstract class AbstractMyTestCase extends AbstractJUnit4SpringContextTests 

而“单位”测试如下:

 public class FooTest extends AbstractMyTestCase 

使用自动assembly的属性。

在不同(集成测试)环境中运行测试的最佳方法是什么? 对测试进行子类化并覆盖ContextConfiguration?

 @ContextConfiguration(locations = { "/my_spring_integration_test.xml" }) public class FooIntegrationTest extends FooTest 

这是否有效(我目前无法在此轻松测试)? 这种方法的问题是“@ContextConfiguration(locations = {”/ my_spring_integration_test.xml“})”重复了很多。

有什么建议么?

此致,弗洛里安

我扩展了GenericXmlContextLoader

public class MyContextLoader extends GenericXmlContextLoader {

并覆盖了

protected String[] generateDefaultLocations(Class clazz)

收集我可以通过SystemProperty(-Dtest.config =)指定的目录的配置文件名的方法。

我还修改了follwowing方法以不修改任何位置

 @Override protected String[] modifyLocations(Class clazz, String... locations) { return locations; } 

我像这样使用这个上下文加载器

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = MyContextLoader.class) public class Test { .... } 

使用指示配置文件源的SystemProperty运行测试,现在可以使用完全不同的配置。

SystemProperty的使用当然只是指定配置位置的一种策略。 您可以在generateDefaultLocations()执行任何操作。


编辑:

此解决方案使您可以使用完整的不同应用程序上下文配置(例如,对于模拟对象)而不仅仅是不同的属性 您不需要构建步骤即可将所有内容部署到“类路径”位置。 如果没有给出系统属性,我的具体实现还使用用户名作为默认值来查找配置目录(src / test / resources / {user})(使得为项目中的所有开发人员维护特定的测试环境变得容易)。

PropertyPlaceholder的使用仍然是可行的并且是推荐的。


编辑

Spring 3.1.0版将支持XML配置文件/环境抽象 ,类似于我的解决方案,可以为不同的环境/配置文件选择配置文件。

我会选择这个版本:

 ContextConfiguration(locations = { "/my_spring_test.xml" }) public abstract class AbstractMyTestCase extends AbstractJUnit4SpringContextTests 

my_spring_test.xml ,我使用了PropertyPlaceHolderConfigurer机制。

JPA示例:

                    

现在,您需要做的就是在类路径上有不同版本的test.properties,用于内存和实际集成测试(当然还需要存在相应的驱动程序类)。 您甚至可以设置系统属性来覆盖属性值。


如果你想用maven准备这个,你会发现用maven复制文件并不简单。 您将需要一种执行代码的方法,标准选择是maven-antrun-plugin和gmaven-maven-plugin 。

无论哪种方式:有两个配置文件,例如在src / main / config中添加两个插件执行,一个是阶段generate-test-resources ,另一个是阶段pre-integration-test 。 这是GMaven版本:

  org.codehaus.gmaven gmaven-plugin 1.3   pre-integration-test  execute    new File( pom.build.testOutputDirectory, "test.properties" ).text = new File( pom.basedir, "src/main/config/int-test.properties" ).text;     generate-test-resources  execute    new File( pom.build.testOutputDirectory, "test.properties" ).text = new File( pom.basedir, "src/main/config/memory-test.properties" ).text;      

我没有成功使用Spring 3.x上下文:property-placeholder标记。 我使用旧的时尚bean标签和属性文件,并能够在我的代码和我的数据库之间建立连接,如下所示:

               

这是属性文件的示例:

 JDBC_URL=jdbc:oracle:thin:@myDB:1521:mySchema JDBC_USERNAME=username JDBC_PASSWORD=password 

然后我像这样设置我的JUnit测试:

 @ContextConfiguration(locations = {"/com/my/pkg/test-system-context.xml"}) @RunWith(SpringJUnit4ClassRunner.class) public class HeaderDaoTest { @Autowired HeaderDao headerDao; @Test public void validateHeaderId() { int headerId = 0; headerId = headerDao.getHeaderId(); assertNotSame(0,headerId); } } 

这对我有用,但每个人做的事情都有所不同。 希望这可以帮助。

我最近遇到了同样的问题并查看了@ContextConfiguration注释的文档 ,我注意到了inheritLocations选项。

通过将此添加到我的class级,例如

 @ContextConfiguration(locations = { "/my_spring_integration_test.xml" }, inheritLocations=false) public class FooIntegrationTest extends FooTest 

我发现我能够根据需要覆盖ContextConfiguration。