【问题标题】:What is the correct way to write to temp file during unit tests with Maven?在使用 Maven 进行单元测试期间写入临时文件的正确方法是什么?
【发布时间】:2012-09-13 05:59:17
【问题描述】:

我编写了一个单元测试,它将文件写入文件系统,但没有写入工作目录的路径;所以如果从项目目录执行,它会写入项目根目录,如果在项目父目录中,它会写入父根目录。

那么写入目标目录的正确方法是什么?很可能是目标目录中的一个目录?

如果我很简单地使用文件指定target/,它将写入父项目目标而不是项目目标。

更新:我实际上想要测试完成后的文件。该文件用于需要发送给第三方的第三方提取格式。可以打开/关闭测试,以便我仅在文件格式更改以重新批准时运行。文件的去向不是什么大问题,但我想要一些容易找到的东西。

【问题讨论】:

    标签: java maven junit4


    【解决方案1】:

    您可以尝试使用TemporaryFolder JUnit @Rule,如here 所述

    TemporaryFolder 在系统属性 java.io.tmpdir 指定的默认临时文件目录中创建一个文件夹。 newFile 方法在临时目录中创建一个新文件,newFolder 方法创建一个新文件夹。

    当测试方法完成时,JUnit 会自动删除 TemporaryFolder 中的所有文件和目录,包括 TemporaryFolder。 JUnit 保证删除资源,无论测试通过还是失败。


    问题更新后

    您可以更改maven-surefire-plugin使用的工作目录。

    <plugins>
        [...]
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.12.3</version>
            <configuration>
              <workingDirectory>${project.build.directory}</workingDirectory>
            </configuration>
          </plugin>
        [...]
    </plugins>
    

    您可以将该工作目录更改为测试所需的任何内容,例如 ${project.build.directory}/my_special_dir/

    surefire 插件中的工作目录仅影响正在运行的测试,并且仅适用于由 maven 执行的测试。如果您在 IDE 中运行测试,则工作目录将是其他目录。

    【讨论】:

    • 感谢 maba,这是一个与 Bohemian 类似的问题,文件最终位于一个不起眼的位置。我实际上想要测试完成后的文件。
    • @BrettRyan 好的,更新了如何更改 surefire 插件的工作目录。这应该可以解决问题。
    • 太棒了,感谢 maba,这非常完美,并且在运行测试的所有机器上始终保持一致。
    • 感谢您留下原始答案。这正是我所需要的。
    • JUNIT 不保证自动删除你必须这样做 @Rule public TemporaryFolder folder = TemporaryFolder.builder().assureDeletion().build();
    【解决方案2】:

    无需重新发明轮子...

    JDK 提供了一种创建临时文件的方法,以及一种在退出时自动删除它的方法:

    File file = File.createTempFile( "some-prefix", "some-ext");
    file.deleteOnExit();
    

    使用该文件,当您的测试完成时它会被自动删除。仅此而已。

    要指定用于临时文件的目录,请使用重载方法:

    File file = File.createTempFile( "prefix", "ext", new File("/some/dir/path"));
    

    【讨论】:

    • 感谢 Bohemian,我实际上希望文件在退出后保留,以便将其发送给供应商。我想系统临时目录很好,虽然我确实希望将它放在目标目录中。
    • 我刚刚尝试过这个,结果发现该文件位于如此隐蔽的地方,使用起来并不明智。结束于/var/folders/xf/scvh7yr11m1glr4b663n1hcsnv5lf0/T/test2614442099335581603.xml
    • @BrettRyan 没问题 - 您可以指定用于临时文件的目录 - 请参阅编辑后的答案
    • 感谢 Bohemian,我确实看到了能够设置临时目录的优点,尽管我确实喜欢将它放在目标目录下的可靠位置,而不是要求存在特定位置机器。
    【解决方案3】:

    我会编写一个例程来确定文件应该写入的位置,然后我会对其进行统一测试,通常我会尽量避免(尽可能)在单元测试中访问持久数据,例如文件 IO 或数据库访问,这有性能原因和其他人。

    看看这个答案:https://stackoverflow.com/a/8032504/395659

    【讨论】:

    • 感谢 O.D,直到现在我才不得不这样做。我编写了测试来编写一个文件,该文件将在生产代码中发送给其他供应商。我的测试将文件写入磁盘,以便我发送给供应商以获得批准,一旦获得批准,测试将不再需要,但在以后发生变化并需要“重新批准”输出时可能会很有用。
    • 但是您为什么要为此目的使用“单元测试”?我认为甚至有一个带有 main() 方法的单独类来服务于这种目的比滥用单元测试更合适
    【解决方案4】:

    您希望能够从 IDE 和 Maven 运行您的测试,因此最佳做法是编写您的测试,这样它们就不会假定它们是在 Maven 中运行的。

    处理临时文件的最佳方法之一是使用junit rules。这使您可以依靠规则为您清理。

    【讨论】:

      【解决方案5】:

      事先声明,我强烈反对在单元测试中做这样的事情。我还没有真正尝试过,但它应该可以工作:

      假设您使用的是surefire插件,从它引用的文档中您可以通过System.getProperty("basedir")访问被测项目的基本目录。获取它并在 basedir/target 下创建文件。

      一种更“合适”的方式(因为我们可能有机会将输出目录配置为其他内容,您可以将surefire插件配置更改为如下内容:

      <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.6</version>
          <configuration>
              <systemPropertyVariables>
                  <myOutDir>${project.build.outputDirectory}</myOutDir>
              </systemPropertyVariables>
          </configuration>
      </plugin>
      

      那么你就可以在你的测试中通过System.getProperty("myOutDir")得到实际的输出目录了。

      【讨论】:

        【解决方案6】:

        临时文件应创建到临时目录中。使用调用System.getProperty("java.io.tmpdir")检索它

        临时文件应该是临时文件,即在不需要时应将其删除。要实现这一点,请不要忘记在 finally 块或测试后运行的代码中删除它,即:

        File tmpFile = ...
        try {
           // deal with tempFile
        } finally {
            tempFile.delete();
        }
        

        和/或

        public class MyTestCase {
            private File tmpFile = null;
        
            @Before
            public void setUp() {
                tmpFile = ...;
            }
        
            @Test
            public void setUp() {
                // deal with tmpFile
            }
        
            @After
            public void setUp() {
                tmpFile.delete();
            }
        }
        

        如果可能,请使用File.createTempFile(String prefix, String suffix),即您可以使用createTempFile()生成的具有特殊名称的文件。

        使用file.deleteOnExit()。这会创建在 JVM 终止时自动删除文件的钩子。只有当 JVM 被 kill -9 杀死时,该文件才会保留,因此它没有机会运行关闭代码。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-11-08
          • 2022-01-06
          • 2014-09-01
          • 2014-03-04
          • 1970-01-01
          • 2019-12-13
          • 2017-02-23
          • 1970-01-01
          相关资源
          最近更新 更多