maven测试无法加载跨模块资源/属性?

时间:2010-06-05 17:15:04

标签: unit-testing testing maven-2 maven

我有一个带有一些模块的maven mantained项目。 一个模块包含一个XML文件和一个解析类。

第二个模块取决于第一个模块。 有一个类在第一个模块中调用解析类,但maven似乎无法在第二个模块中测试该类。 Maven测试报告:

java.lang.NullPointerException
 at java.util.Properties.loadFromXML(Properties.java:851)
 at foo.firstModule.Parser.<init>(Parser.java:92)
 at foo.secondModule.Program.<init>(Program.java:84)

在“Parser.java”(在第一个模块中)中,它使用Properties和InputStream来读取/解析XML文件:

InputStream xmlStream = getClass().getResourceAsStream("Data.xml");
Properties properties = new Properties();
properties.loadFromXML(xmlStream);

“data.xml”位于第一个模块的resources / foo / firstModule目录中,它在第一个模块中测试OK。

在测试第二个模块时,maven似乎无法在第一个模块中正确加载Data.xml。

我认为我可以使用 maven-dependency-plugin:unpack 来解决问题。在第二个模块的POM文件中,我添加了以下片段:

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-dependency-plugin</artifactId>
 <version>2.1</version>
  <executions>
    <execution>
      <id>data-copying</id>
      <phase>test-compile</phase>
      <goals>
        <goal>unpack</goal>
      </goals>
      <configuration>
        <artifactItems>
          <artifactItem>
            <groupId>foo</groupId>
            <artifactId>firstModule</artifactId>
            <type>jar</type>
            <includes>foo/firstModule/Data.xml</includes>
            <outputDirectory>${project.build.directory}/classes</outputDirectory>
          </artifactItem>
        </artifactItems>
      </configuration>
    </execution>        
  </executions>
</plugin>

在这个POM文件中,我尝试解压缩第一个模块,并将Data.xml复制到classes / foo / firstModule /目录,然后运行测试。

实际上,它被复制到正确的目录,我可以在“target / classes / foo / firstModule”目录中找到“Data.xml”文件。但是maven测试仍然抱怨它无法读取文件(Properties.loadFromXML()抛出NPE)。

我不知道如何解决这个问题。 我尝试了其他输出目录,例如$ {project.build.directory} / resources和$ {project.build.directory} / test-classes,但都是徒劳的......

现在有什么建议吗?谢谢你提前。

环境:Maven 2.2.1,eclipse,m2eclipse

----更新----

对不起,我忘了提到,第2个模块中的程序扩展第1个模块中的Parser, 在Parser的构造函数中,属性被加载和解析。 事实上,Program是另一个具有更多功能的Parser ......

我认为可能是因为程序扩展Parser ,导致问题(可能是类加载器问题)。

如果我断开“继承”,在程序中初始化(新)解析器,它就可以了,测试通过! 但是我无法改变继承关系......它的设计......

现在有什么解决方案吗?

----用完整代码更新----

这是第一个模块中的Parser:

package foo.firstModule;

import java.io.IOException;
import java.io.InputStream;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;

public class Parser
{
  private Properties properties;

  public Parser()
  {
    InputStream xmlStream = getClass().getResourceAsStream("Data.xml");
    properties = new Properties();
    try
    {
      properties.loadFromXML(xmlStream);
    }
    catch (InvalidPropertiesFormatException e)
    {
      e.printStackTrace();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  public Properties getProperties()
  {
    return properties;
  }
}

这是Parser的测试用例,已通过。

package foo.firstModule;

import junit.framework.TestCase;

public class ParserTest extends TestCase
{
  public void testParser()
  {
    Parser p = new Parser();
    assertEquals(64 , p.getProperties().size());
  }
}

这是第二个模块中的ParserExtend,它在第一个模块中扩展了Parser:

package foo.secondModule;

import java.util.Properties;

import foo.firstModule.Parser;

public class ParserExtend extends Parser
{
  private Properties properties;

  public ParserExtend()
  {
    this.properties = getProperties();
  }

  public int getSize()
  {
    return properties.size();
  }
}

这是ParserExtend的测试用例:

package foo.secondModule;

import junit.framework.TestCase;

public class ParserExtendTest extends TestCase
{
  public void testParserExtend()
  {
    ParserExtend pe = new ParserExtend();
    assertEquals(64 , pe.getSize());
  }
}

上述测试用例失败,因为 Properties.loadFromXML (Properties.java:851)抛出NPE

但是,如果我不扩展Parser,只需更新Parser:

package foo.secondModule;

import java.util.Properties;

import foo.firstModule.Parser;

public class ParserInit
{
  private Properties properties;

  public ParserInit()
  {
    Parser p = new Parser();
    this.properties = p.getProperties();
  }

  public int getSize()
  {
    return properties.size();
  }
}

这是测试用例:

package foo.secondModule;

import junit.framework.TestCase;

public class ParserInitTest extends TestCase
{
  public void testParserInit()
  {
    ParserInit pi = new ParserInit();
    assertEquals(64 , pi.getSize());
  }
}

测试用例通过了!

这是我的整个测试场景。 有谁能找到如何通过ParserExtend的测试用例? 谢谢你提前。

2 个答案:

答案 0 :(得分:0)

  

在测试第二个模块时,maven似乎无法在第一个模块中正确加载Data.xml。

我创建了完全相同的结构,但无法重现您的问题。第二个模块中的Program类使用第一个模块中的Parser类,该类从XML文件加载属性而没有任何问题。在Eclipse和命令行下测试。

  

我认为我可以使用maven-dependency-plugin:unpack来解决问题。

使用dependency:unpack绝对不是解决方案,如果第一个JAR包含foo/firstModule/Data.xml,则使用其他模块中的Parser类应该可以正常工作。其他地方一定有问题。如果你可以上传一个代表性的测试项目,那么请这样做,我会看看ti。如果没有允许重现的项目,我担心你得到的最好答案是“调试你的代码”:)

答案 1 :(得分:0)

我同意,这听起来像是类加载器问题。

如果您一直打算在/foo/firstModule/Data.xml位置使用Data.xml,请尝试foo.firstModule.Parser

InputStream xmlStream = getClass().getResourceAsStream("/foo/firstModule/Data.xml");

或者,如果你明确地希望找到“本地”Data.xml的行为应该在其他地方重用firstModule(例如secondModule或thirdModule有自己的Data.xml),试试这个:

InputStream xmlStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("Data.xml");