【问题标题】:How to use dynamic partial mocking with JMockit and Logger interface?如何通过 JMockit 和 Logger 接口使用动态部分模拟?
【发布时间】:2015-02-12 16:00:13
【问题描述】:

我一直在使用 JMockit 和它公认的陡峭的学习曲线。我对一般的嘲笑很陌生,所以请原谅我的无知。

我正在尝试模拟 Logger 界面,以便我可以验证 catch 语句是否正常工作。将此称为理解 JMockit 如何工作的练习。 Logger 接口的实现类是 Log4jLoggerAdapter 所以我想如果我将它的一个实例传递给我的 Expectations() 块,JMockit 将使用动态部分模拟并“查看”我的记录器语句。相反,我收到以下错误:

mockit.internal.MissingInvocation:缺少调用:org.slf4j.impl.Log4jLoggerAdapter#error(String msg, Throwable t)

正在测试的类

public class MyLoggedClass {
  private static final Logger LOGGER = LoggerFactory.getLogger(MyLoggedClass.class);

  ... // Other variables

  @Override
  public void connect() {
      String info = getServiceInfo();
      try {
        connector = MyConnectionFactory.connect(info);
      } catch (Exception e) {
        LOGGER.error("Exception connecting to your service with: " + info, e);
      }
  }

  ...  // Other methods
}

我的@Test

public class MyLoggedClassTest {

@Tested
MyLoggedClass myLoggedClass;

@Test
public void myLoggingTest(@Mocked final Log4jLoggerAdapter logger){

    new Expectations(MyConnectionFactory.class, logger){{
      MyConnectionFactory.connect(anyString);
      result = new Exception();

      logger.error(anyString, (Throwable)any);
    }};

    myLoggedClass.connect();
}

我会详细介绍我尝试过的其他方法,但这一页会变成一本书。这是我最好的方法。有什么想法吗?

* 更新 *(是的,很快)

我将@Mocked 更改为@Cascading 并从我的Expectations 签名中删除了记录器字段并且它起作用了。我不明白为什么。有人可以提供解释吗?摸索,直到你偶然发现一些有用但你不明白的东西,这不是成功的秘诀。见下文:

@Test
public void myLoggingTest(@Cascading final Log4jLoggerAdapter logger){

    new Expectations(MyConnectionFactory.class){{
      MyConnectionFactory.connect(anyString);
      result = new Exception();

      logger.error(anyString, (Throwable)any);
    }};

    myLoggedClass.connect();
}

【问题讨论】:

    标签: unit-testing logging jmockit


    【解决方案1】:

    在这种情况下不需要部分模拟,只需以通常的方式模拟 MyConnectionFactory。唯一棘手的部分是如何模拟实现Logger 接口的类,考虑到它是从静态类初始化程序实例化的。碰巧的是,模拟 API 中有一个功能(使用 JMockit 1.14):

    public class MyLoggedClassTest
    {
        @Tested MyLoggedClass myLoggedClass;
    
        @Test
        public void myLoggingTest(
            @Mocked MyConnectionFactory conFac, 
            @Capturing final Logger logger)
        {
            new Expectations() {{
                MyConnectionFactory.connect(anyString);
                result = new Exception();
            }};
    
            myLoggedClass.connect();
    
            new Verifications() {{
                logger.error(anyString, (Throwable)any);
            }};
        }
    }
    

    使用@Capturing 模拟类型,任何实现类都会被模拟,因此测试不需要知道Log4jLoggerAdapter

    【讨论】:

    • 我阅读了关于该注释的文档,这似乎是有道理的。我在一个项目中使用 1.5 版,而 @Capturing 注释在代码完成中弹出,它似乎不起作用。我在另一个项目中尝试了 1.14 并且您的建议效果很好。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 2016-05-26
    相关资源
    最近更新 更多