使用 TemporaryFolder 的 JUnit 测试中的 AccessDeniedException

AccessDeniedException in JUnit test using a TemporaryFolder

我做的 JUnit 测试有问题。如果传递的 InputStream 不支持 mark/reset.

,我正在测试的方法采用 InputStream 应该抛出异常

我 运行 遇到的问题是,当不支持 mark/reset 的 InputStream 通过(在下面发布)时,我的测试确保抛出异常扔 AccessDeniedException.

public class IOTest{

    @Rule
    public TemporaryFolder tempFolder = TemporaryFolder()

    @Before
    public void createFolder() throws IOException {
        Files.createDirectories(tempFolder.getRoot().toPath().resolve("testFile"));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testDetectCharsetOnlyAcceptsMarkResetSupportedInputStreams() throws IOException {
        final Path testPath = tempFolder.getRoot().toPath().resolve("testFile");
        final InputStream testStream = Files.newInputStream(testPath);
        IO.detectCharset(testStream);
    }
}

我认为我 运行 遇到的问题与访问临时文件夹有关,但我不知道如何避免这个问题。

这是我 运行 此测试时打印的堆栈跟踪:

java.lang.Exception: Unexpected exception, expected<java.lang.IllegalArgumentException> but was<java.nio.file.AccessDeniedException>
    at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.rules.ExternalResource.evaluate(ExternalResource.java:48)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access[=11=]0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: java.nio.file.AccessDeniedException: C:\Users\antho\AppData\Local\Temp\junit4390480127201295432\testFile
    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
    at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:230)
    at java.nio.file.Files.newByteChannel(Files.java:361)
    at java.nio.file.Files.newByteChannel(Files.java:407)
    at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384)
    at java.nio.file.Files.newInputStream(Files.java:152)
    at com.bunnell.anthony.booker.IOTest.testDetectCharsetOnlyAcceptsMarkResetSupportedInputStreams(IOTest.java:65)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:19)
    ... 24 more

我猜它与权限和 OS 有关,但我不确定如何解决这个问题。如果有帮助,我正在使用 Windows 10.

您正在尝试从 testFile 中读取,它不是文件而是目录;您正在使用

创建
Files.createDirectories(tempFolder.getRoot().toPath().resolve("testFile"));

谁的 documentation 说:

Creates a directory by creating all nonexistent parent directories first.

(强调我的)

为了保持 JUnit 测试的可移植性和简单性,我建议完全删除外部文件依赖性。

您可以通过两种方式执行此操作:

  1. 从内部的东西创建一个 InputStream,比如字符串或字节数组。 Here is how with strings

  2. 使用模拟框架,例如 Mockito,创建一个虚拟 InputStream,其功能刚好足以确认该方法有效。这是我的首选策略,因为模拟会产生更清晰的测试。