Mockito doThrow() 没有按照我的预期行事

Mockito doThrow() not acting as I expect

我正在处理与使用 WebDrivers、WebElements 等的项目相关的单元测试。我在模拟连接和所有方面都走得很远,但我遇到了一个问题。

我的 class 中有一个 try 块看起来类似于

class MyClass {

    myMethod() {
        (...)
        try {
            WebElement element = webDriver.findElement(By.id(elementId));
            element.click();
        } catch (NoSuchElementException e) {
            throw new MyException("Unable to locate element!", e);
        }
        (...)
    }
}

现在我正在尝试编写一个未找到该元素的测试用例

class MyTestClass {

    testMyMethod() {
        WebElement mockedElement = Mockito.mock(WebElement.class);
        Mockito.when(mockedWebDriver.findElement(By.id(Mockito.anyString()))).thenReturn(mockedElement);
        Mockito.doThrow(NoSuchElementException.class).when(mockedAllowElement).click();

        try {
            mockedObjectOfMyClass.myMethod()
            Assert.fail();
        } catch (MyException e) {
            Assert.assertTrue(e.getCause() instanceof NoSuchElementException);
        }
    }
}

我的问题是我得到了可爱的 NoSuchElementException 而不是预期的 MyException:

    java.util.NoSuchElementException
    Process finished with exit code -1

我检查了所有我能想到的。在测试过程中,测试方法中所有模拟对象的 hashCode 与真实方法中的相同,myMethod 运行到 "element.click()"。但是异常没有被catch块捕获。

我一定是遗漏了一些东西,我对 Mockito 和 UnitTesting 还很陌生。

希望我在缩短我的逻辑时没有遗漏任何重要的东西:)。

我将不胜感激任何想法或提示

(编辑)

感谢您的快速回复,这里是完整的堆栈跟踪:

java.util.NoSuchElementException: this is mine
    at yandex.TokenGeneratorTest.testGetVerificationCodeNoElement(TokenGeneratorTest.java:308)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    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.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[=13=]0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

我认为您应该重构代码以使测试更容易。如果它是遗留代码,那么你就得靠自己了。

方法 testMyMethod() 可能会请求 webDriver 并声明抛出异常 NoSuchElementException。

所以有类似

的东西
 class MyTestClass  {

    testMyMethod(WebDriver webDriver) throws NoSuchElementException { 
      ...
    }

现在你的测试可能如下所示。

class MyTestClass {

     @Test(expected = NoSuchElementException.class)
     testMyMethod() {
         WebDriver mockedWebDriver = Mockito.mock(WebDriver.class);
         WebElement mockedElement = Mockito.mock(WebElement.class);
         Mockito.doThrow(NoSuchElementException.class).when(mockedElement).click();

    Mockito.when( mockedWebDriver.findElement( By.id( Mockito.anyString()))).thenReturn( mockedElement);

    MyClass myClass = new MyClass();
    myClass.myMethod(mockedWebDriver)

  }
}

此外,我高度怀疑是在调用 findElement(...) 期间抛出异常,而不是在单击期间抛出异常。但我猜你离代码更近了。

感谢您的所有想法。

我刚刚度过了一个 "watch out when using alt + enter" 时刻。

代码工作得很好,除了我的测试方法抛出了一个 java.util.NoSuchElementException 而不是我的代码捕获的 org.openqa.selenium.NoSuchElementException

更改此设置解决了我的问题,再次感谢您的宝贵时间:)