如果测试运行正常,为什么我会得到一个Reflection异常NoSuchMethodException

时间:2017-09-08 13:07:03

标签: java reflection junit mocking private-methods

我正在使用Reflection来模拟私有方法(我不想讨论是否有意义)。

任何人都知道为什么?我会在这里让我的testClass源代码有所帮助。我已经尝试了很多互联网帮助和方法来解决这个问题,但没有一个对我有用。

public class testProtexManagerProcessRequiredFile {

  @Mock
  ProtexManager PxManager;


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

  @Test
  public void processRequiredFileTest() throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, InstantiationException {

    Method method;
    try {
      method = ProtexManager.class.getDeclaredMethod("processRequiredFile", File.class);
      method.setAccessible(true);

      File FileExample = new File();
      String NameExample = "Nome";
      File outputs = new File();
      outputs = (File) Mockito.when(method.invoke(PxManager, FileExample,NameExample)).thenReturn(FileExample);
      assertNotNull(outputs);
      assertEquals(outputs, method.invoke(PxManager, FileExample,NameExample));
    } catch (NoSuchMethodException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
   System.out.println("Teste Concluido."); 
  }
}

这是方法代码:

 private File processRequiredFile(File file, String name) {
    if (!file.exists()) {
      this.message = name + " file not found at location: " + file;
      this.msgResponse.addMsgList(MsgCode.FAILURE, MsgLevel.ERROR, this.message, StringUtils.EMPTY);
    }
    return file;
  }

谢谢大家帮助我解决疑惑。

2 个答案:

答案 0 :(得分:1)

要回答你的问题,

因为你抓住了NoSuchMethodException。为了让测试失败,你必须以某种方式在测试执行期间得到一些异常或错误

要跟进评论,以下是测试此方法的方法:

// let's assume there are getter for this.message / this.msgResponse 
// and this method is in the class foo.bar.Foobar
protected File processRequiredFile(File file, String name) {
    if (!file.exists()) {
      this.message = name + " file not found at location: " + file;
      this.msgResponse.addMsgList(MsgCode.FAILURE, MsgLevel.ERROR, this.message, StringUtils.EMPTY);
    }
    return file;
}

在测试班foo.bar.FoobarTest中:

@Mock
private File file;

private Foobar foobar = new Foobar(); 

@Test
public void testWithNonExistingFile() {
    Mockito.when(this.file.exists()).thenReturn(false); // this is to illustrate, you could also use some non existent file: new File("/does-not-exists.foo")
    File result = this.foobar.processRequiredFile(this.file, "some name");
    assertThat(result).isEqualTo(this.file);
    assertThat(foobar.getMsgResponse()).isNotEmpty(); // TODO: better assertion
    assertThat(foobar.getMessage()).isEqualTo( "some name file not found at location: " + this.file);
}

@Test
public void testWithExistingFile() {
    Mockito.when(this.file.exists()).thenReturn(true);
    File result = this.foobar.processRequiredFile(this.file, "some name");
    assertThat(result).isEqualTo(this.file);
    assertThat(foobar.getMsgResponse()).isEmpty();
    assertThat(foobar.getMessage()).isNull();
}

测试中的类(即Foobar)已经过测试,它使用它的实例并调用其方法。模拟用于替换我们没有的东西(这里是一个文件来说明,但它通常更复杂)

答案 1 :(得分:0)

你的实际问题是什么?为什么测试用例成功?这已在评论中得到解答。你捕获异常并基本上忽略它。如果你想在STDERR上看到堆栈跟踪并让测试用例失败,你必须自己启动失败的过程,例如通过调用

throw (AssertionFailedError) new AssertionFailedError("method not found").initCause(e);

这个构造看起来很奇怪,但JUnit 3(我假设你使用的是给定代码)没有带有构造函数的AssertionFailedError,允许传递一个原因。这样您就可以在IDE中看到堆栈跟踪,并且可以在构建过程中创建的JUnit报告中看到。

或者您的问题是为什么找不到特定的方法?一个原因可能是someClass.getDeclaredMethod仅在该特定类中声明方法时才返回结果。如果该类有一个继承此方法的超类,则在调用getDeclaredMethod时必须使用超类来获取该方法。

如果您不知道哪个类实际包含方法,则必须遍历所有超类,直到达到“结束”:

Class<?> clazz = ProtexManager.class;
while (clazz != null) {
    try {
        return clazz.getDeclaredMethod("processRequiredFile", File.class);
    catch(NoSuchMethodException e) {
        clazz = clazz.getSuperClass();
    }
}

该代码块吞噬了NoSuchMethodException,但我不想做一些比说明这个想法更复杂的事情。

找不到该方法的另一个原因可能是所讨论的类有方法processRequiredFile(java.io.File)而不是processRequiredFile(com.blackducksoftware.sdk.codecenter.deeplicense.data.File)。此外,您稍后使用三个参数(PxManager,文件,字符串)通过method.invoke调用该方法,因此您getDeclaredMethod的调用缺少参数类,或者您invoke的调用将在以后失败,因为声明方法和传递参数之间的区别。