【问题标题】:How to test that catch (Exception e) { e.printStackTrace();} invoked如何测试调用的 catch (Exception e) { e.printStackTrace();}
【发布时间】:2020-05-05 10:46:01
【问题描述】:

我需要达到 95% 的测试覆盖率(我的任务)。我在上课时遇到问题

    public class Context {

    public static <T> T getObject(Class<T> clazz) {
        Object bean = null;

        try {
            bean = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return (T) bean;
    }

    private Context() {
    }
}

要达到 95%,我需要检查 e.printStackTrace(); 是否在抛出异常时被调用。 我尝试了不同的方法,但它们都不起作用。我将不胜感激。

【问题讨论】:

  • 检查是否返回 null。但是,老实说,您不想捕获该异常:只需将异常传播给调用者即可。
  • 你目前的测试用例怎么样?
  • 你不应该检查 e.printStackTrace();被调用。只需确保调用 clazz.newInstance() 时在您的测试用例中引发异常。
  • 我同意@matrixguy。您不需要对 Java API 进行单元测试;这应该由实施团队(Oracle 等)完成。 printStackTrace()java.lang 包的一部分

标签: java mockito junit5


【解决方案1】:

要验证 printStackTrace 是否被调用,我能想到的最简单的方法是 spy/mock Exception 对象。

使用 mockito,您可以传入一个模拟 Class,它会在调用 newInstance 时抛出一个间谍 Exception

Class<?> mockClass = mock(Class.class);
Exception e = Mockito.spy(new Exception());
Mockito.doThrow(e).when(mockClass).newInstance();

context.getObject(mockClass);

Mockito.verify(e).printStackTrace();

如果你知道Exception 将被扔到哪里,你也可以用powermock 和whenNew 做一些事情(这样你就可以@PrepareForTest 那个类)。

Exception e = Mockito.spy(new Exception());
PowerMockito.whenNew(Exception.class).thenReturn(e);

context.getObject(SomeService.class);

Mockito.verify(e).printStackTrace();

注意:我还没有编译和测试上述任何一个(并且始终以各种方式将 MockitoPowerMockito 类名弄错)。


如果您在没有库的情况下决心这样做,您可以执行以下操作:

  1. 创建自定义Exception 类型,在调用该方法时显式设置一些标志:
  2. 创建一个自定义class,在调用无参数构造函数时抛出上述Exception
  3. 将此自定义类的.class 传递到您的方法中,并验证标志是否已设置。

类似:

class MyException extends Exception {
    public static boolean printStackTraceCalled = false;

    @Override
    public void printStackTrace() {
        MyException.printStackTraceCalled = true;
        super.printStackTrace();
    }
}

class MyClass {
    MyClass() {
        throw new MyException();
    }
}

@Test
void testThing() {
    context.getObject(MyClass.class);

    Assertions.assertTrue(MyException.printStackTraceCalled);
}

也就是说,这只是如何你会这样做......我并不是说这是一个好主意。这是处理Exceptions 的一种糟糕方式,而且针对特定的代码覆盖率百分比通常毫无意义。

【讨论】:

    【解决方案2】:

    这就是我解决这个问题的方法。我稍微重构了一下代码:

     private static final Logger LOGGER = Logger.getLogger(Context.class.getName());
    
        public <T> T getObject(Class<T> clazz) {
            T bean = null;
    
            try {
                bean = clazz.getConstructor().newInstance();
            } catch (Exception e) {
                LOGGER.log(Level.INFO, e, () -> "Exception occurred during Context usage whilst created " + clazz.getName());
            }
            return bean;
        }
    

    这是测试:

        @Test
        void getObject_ShouldThrowException() throws Exception {
            Exception mockedException = mock(InstantiationException.class);
            Logger mockedLogger = mock(Logger.class);
    
            class Dummy {
    
                public Dummy() throws Exception {
                    throw mockedException;
                }
            }
    
            try {
                Dummy dummy = context.getObject(Dummy.class);
            } catch (Exception e) {
                verify(mockedLogger, times(1)).log(Level.INFO, anyString());
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2020-07-26
      • 2012-06-04
      • 1970-01-01
      • 1970-01-01
      • 2021-07-10
      • 1970-01-01
      • 2013-06-09
      • 2014-03-18
      相关资源
      最近更新 更多