JUnit AssertionError - 没有抛出预期的异常

JUnit AssertionError - Expected exception not thrown

我正在尝试熟悉 JUnit/Mockito 并使用以下方法尝试进行一些单元测试:

public FSDataInputStream getObj(String hName, Path p) throws IOException {

    String myKey = pathToKey(hName, p);
    FileStatus status = memoryCache.getStatus(p.toString());
    if (status == null) {
      status = getStatus(hName, p, "getObj");
    }
    if (status.isDirectory()) {
        throw new FileNotFoundException("Can't open " + path
  + " because it is a directory");
    }
    InputStream inputStream = new InputStream(bucket, myKey,
    status.getLen(), client, readAhead, inputPolicy);

    return new FSDataInputStream(inputStream);
}

我想测试如果 status.isDirectory == true 会抛出 fileNotFoundException。

我认为我必须调用 getObj() 方法,对于 if (status.isDirectory()) 我必须确保该值为 true。我认为这是通过 when(fileStatus.isDirectory()).thenReturn(true); 完成的我不确定如何调用该方法并确保它发生。

到目前为止,我已经得到了这个 JUnit,但它似乎不正确,因为它返回了以下错误:

public class ClientTest {
    MemoryCache memoryCache = mock(MemoryCache.class);
    FileStatus fileStatus = mock(FileStatus.class);

    @Rule
    public final ExpectedException exception = ExpectedException.none();

    @Test
    public void getObjTest() throws Exception {
        Path path = new Path("xyz://aa-bb-cc/data7-1-23-a.txt");

        when(memoryCache.getFileStatus(path.toString())).thenReturn(fileStatus);
        when(fileStatus.isDirectory()).thenReturn(true);
        exception.expect(FileNotFoundException.class);
    }
}

java.lang.AssertionError: Expected test to throw an instance of java.io.FileNotFoundException at org.junit.Assert.fail(Assert.java:88) at org.junit.rules.ExpectedException.failDueToMissingException(ExpectedException.java:263) at org.junit.rules.ExpectedException.access0(ExpectedException.java:106) at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:245) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:91) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87) at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120) at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122) at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106) at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

任何人都可以告诉我做错了什么吗?

方法 getObj 必须在 class 中声明(我们在 OP 中看不到)但我们假设它在 class:[=22= 中]

public class Foo {
    private MemoryCache memoryCache;

    public Foo(MemoryCache memoryCache) {
        this.memoryCache = memoryCache;
    }

    public FSDataInputStream getObj(String hName, Path p) throws IOException {
        // ...
    }
} 

现在,您的测试可能如下所示:

public class ClientTest {
    private MemoryCache memoryCache = mock(MemoryCache.class);
    private FileStatus fileStatus = mock(FileStatus.class);

    @Rule
    public final ExpectedException exception = ExpectedException.none();

    @Test
    public void getObjTest() throws Exception {
        Path path = new Path("xyz://aa-bb-cc/data7-1-23-a.txt");

        // create the class-under-test, supplying the mocked MemoryCache
        Foo foo = new Foo(memoryCache);

        // establish your expectations on the mocked classes
        // for this test the expectations are:
        // - memoryCache returns the mocked fileStatus    
        // - the mocked fileStatus 'is a' directory        
        when(memoryCache.getFileStatus(path.toString())).thenReturn(fileStatus);
        when(fileStatus.isDirectory()).thenReturn(true);

        // you expect a FileNotFoundExceptionException ...
        exception.expect(FileNotFoundException.class);

        // ... when you invoke getObj
        foo.getObj("aString", path);
    }
}

备注:

  • 您必须在测试中调用 getObj
  • getObj调用必须进入if (status.isDirectory()) { ... }
  • 你必须指示被嘲笑的 MemoryCache 到 return 被嘲笑的 FileStatus
  • 当调用 isDirectory 时,您必须将模拟的 FileStatus 指示为 return true
  • 您必须将模拟的 MemoryCache 提供给正在测试的 Foo 实例,在上面的示例中,这是通过构造函数注入完成的

1) 取消注释第一个 when 语句,因为它是下一个 when 设置工作所必需的。

2)调用被测方法

3) (可选)使用注释进行模拟:

public class ClientTest {

    @Spy
    @InjectMocks
    private Client clientSpy = new Client();

    @Mock
    MemoryCache memoryCache;
    @Mock
    FileStatus fileStatus;

    @Rule
    public final ExpectedException exception = ExpectedException.none();

    @Before
    public void init(){
       MockitoAnnotations.initMocks(this);
    }

    @Test
    public void getObjTest() throws Exception {
       // Arrange
       Path path = new Path("xyz://aa-bb-cc/data7-1-23-a.txt");

        doReturn(Mockito.anyString()).when(clientSpy)
           .pathToKey(Mockito.anyString(), Mockito.anyString());         

        when(memoryCache.getFileStatus(path.toString()))
           .thenReturn(fileStatus);

        when(fileStatus.isDirectory()).thenReturn(true);

        exception.expect(FileNotFoundException.class);

        // Act
        clientSpy.getObj(name, path);
    }
}