【问题标题】:Unit test existence of a directory - Junit目录的单元测试存在 - Junit
【发布时间】:2019-07-01 17:27:14
【问题描述】:

我有一个函数用来检测某个目录路径是否存在。函数如下:

public boolean isRunningOnSandbox() {
   return Files.isDirectory(Paths.get("/mySandbox/cloud/sandbox"));
}

如您所见,它依赖于静态方法 isDirectory。在我的团队中,我们不使用 PowerMock 进行测试。

那么,我该如何测试这个方法呢?我试过写一个像这样的测试:

@Rule
public TemporaryFolder temporaryFolder;

@Test
public void test() throws IOException {
    File parent = new File("/");
    temporaryFolder = new TemporaryFolder(parent);
    temporaryFolder.create();
    File folder = temporaryFolder.newFolder("mySandbox", "cloud", "sandbox");
    subject.isRunningOnSandbox();
}

但是,我得到一个错误

ava.io.IOException: Permission denied

因为它不允许我在根目录下创建临时文件夹。我猜有更好的方法来测试此代码,而不是尝试创建文件夹。

【问题讨论】:

  • 我倾向于允许注入值并使用tempdir 验证方法调用,并断言isRunningOnSandbox 在使用 tempdir 时返回 true,否则返回 false,然后进行额外测试通过另一个测试验证每个区域/env/space/whatever 中的值。
  • 你愿意重构这个紧密耦合的代码并使用依赖倒置来隔离被测代码吗?如果访问实际文件夹,当前示例更多的是集成测试。
  • 我认为您还需要处理该异常并在出现Permissions denied 异常的情况下返回false。
  • 请使用正确的标签,这不是单元测试,而是集成测试

标签: java junit integration-testing


【解决方案1】:

有很多方法可以做到,其中一种可能像下面的那样。
假设isRunningOnSandbox方法在某个类SomeClass中,那么就这样重构这个类:

public class SomeClass {

    public boolean isRunningOnSandbox() {
        return Files.isDirectory(Paths.get(getSanboxPath()));
    }

    protected String getSanboxPath(){
        return "/mySandbox/cloud/sandbox";
    }
}

然后在你的测试中将另一个你可以访问的目录注入到这个类中,例如:

public class SomeClassTest {

    class SomeClassToTest extends SomeClass{
        String folder;
        public SomeClassToTest(String folder){
            this.folder = folder;
        }
        @Override
        protected String getSanboxPath(){
            return folder;
        }
    }

    static String sandboxFolder = "myTestSandobxFolder";

    static Path tempDir;

    @BeforeClass
    public static void createFolder() throws IOException {
        tempDir = Files.createTempDirectory(sandboxFolder);
    }

    @AfterClass
    public static void deleteFolder() throws IOException {
        Files.delete(tempDir);
    }

    @Test
    public void IsRunningOnSandbox_shouldReturnTrueWhenPathExists() throws IOException {
        //given
        SomeClass testedObject = new SomeClassToTest(tempDir.toString());
       //when
        boolean result = testedObject.isRunningOnSandbox();
        //then
        assertThat(result).isTrue();
    }

    @Test
    public void IsRunningOnSandbox_shouldReturnFalseWhenPathDoesNotExist() throws IOException {
        //given
        SomeClass testedObject = new SomeClassToTest("/abcdef123");
        //when
        boolean result = testedObject.isRunningOnSandbox();
        //then
        assertThat(result).isFalse();
    }
}

【讨论】:

    【解决方案2】:

    您展示的功能不适合单元测试:通过单元测试,您试图在小的、孤立的软件片段中找到错误。但是,此示例代码中可能存在哪些与其他组件(即Files 组件、Paths 组件和实际文件系统)无关的错误?

    您示例中的潜在错误与“我调用正确的函数吗?”等问题有关。或“我是否使用适当的参数值调用函数?”或“按预期执行我调用的函数返回参数”或“我使用的路径也是在文件系统中找到的路径”。这不能通过单元测试来检查,但可以通过集成测试来检查。

    想象一下你的想法是错误的。然后,在您的单元测试中,您还将检查相同的错误路径,并且您的单元测试将成功。只有在真实文件系统上将该测试作为集成测试运行时,您才能发现您想到的路径是错误的,并且与文件系统中的实际路径不匹配。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-18
      • 2015-04-25
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      • 2013-05-22
      • 2023-03-15
      相关资源
      最近更新 更多