如何在mockito中模拟class.forname()

ds97pgxw  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(549)

我有一个方法在里面调用class.forname()。当我创建一个单元测试时,它抛出classnotfoundexception。有没有办法模拟class.forname()行为?
需要测试的方法:

public Map<String, Object> invokeOperation(String className, String methodName) {
      try {
         final Class<?> implClass =
                 Class.forName(className);
         final Object obj= implClass.getDeclaredConstructor().newInstance();
         final Class<?>[] parameterTypes = getParamTypes();
         final Object[] args = getParamValues();
         final Method method = obj.getMethod(methodName, parameterTypes);
         final Map<String, Object> result = (Map<String, Object>) method.invoke(obj, args);
         return result;
      } catch (final ClassNotFoundException | InstantiationException e) {
         e.printStackTrace();
      }
}
0s7z1bwu

0s7z1bwu1#

我认为你不应该嘲笑我 Class.forName 方法。
相反,请考虑:
为要在测试中检查的测试创建一个特殊类,并将其放入 src/test/java 如果您使用的是构建系统(比如maven),那么就使用这个文件夹,这样这个类就不会到达生产工件。这将涵盖一条“幸福之路”
如果要测试异常,请考虑以下重构(我将调用包含 invokeOperation 方法 OperationInvoker ):

public class OperationInvoker {
  private ClassByNameResolver classByNameResolver;
  public OperationInvoker(ClassByNameResolver classByNameResolver) {
     this.classByNameResolver = classByNameResolver;
  }

  public Map<String, Object> invokeOperation(String className, String methodName) {
      try {
         final Class<?> implClass = classByNameResolver.resolveClass(className);

         final Object obj= implClass.getDeclaredConstructor().newInstance();
         final Class<?>[] parameterTypes = getParamTypes();
         final Object[] args = getParamValues();
         final Method method = obj.getMethod(methodName, parameterTypes);
         final Map<String, Object> result = (Map<String, Object>) method.invoke(obj, args);
         return result;
      } catch (final ClassNotFoundException | InstantiationException e) {
         e.printStackTrace();
      }
  }
}

public class ClassByNameResolver { // or provide an interface and implementation
   public Class<?> resolveClass(String name) throws ... {
      return Class.forName(name);
   }
}

现在,这允许轻松地模仿 ClassByNameResolver 用mockito来模拟抛出异常的情况。
这是一个品味的问题,但在这种情况下,单元测试可以同时涵盖这两个类(unit=two class)

bqf10yzr

bqf10yzr2#

mockito不支持模拟静态方法。如果您真的想这么做,可以看看powermock。
但是,正如前面提到的,一个更好的方法是不要嘲笑任何东西。只需将一个真实有效的类名(及其方法名)传递给该方法,并测试它是否正常工作。我还建议只为测试目的创建一个类(或多个类),这样就不需要在每次更改类时修复测试。

相关问题