【问题标题】:Mockito and interface eventMockito 和界面事件
【发布时间】:2016-02-01 14:39:34
【问题描述】:

我正在使用 mockito 编写集成测试。 被测单元通过接口连接到模拟对象(objA)。当被模拟的对象触发一个事件并且被测单元正在监听它时,我试图模仿的功能就会发生。

界面:

public interface MyInterfaceAPI{
   void fireyMyEvent(String msg);
}

被测单元:

public class UnitUnderTest{

    ObjA objA;

    public UnitUnderTest(ObjA objA_t) {
         objA = objA_t;
         objA.addMyListener(new addMyHandler()); 
    }

    class addMyHandler implements MyInterfaceAPI{
       @Override
       public void fireyMyEvent(String msg) {
             System.out.println(msg);
       };
    };
};

测试:

 public class MyTest {

     @org.junit.Test
     public void run() {

         ObjA  mockObjA = mock(ObjA .class);    
         UnitUnderTest spyController = Mockito.spy(new UnitUnderTest());

         MyInterfaceAPI mo2uut= mock(MyInterfaceAPI.class);
         mo2uut.fireyMyEvent("hello from test"); 
     }
 }

我的问题是在测试中,如何将 mo2uut('mocked object' 到 'unit under test')连接到 UnitUnderTest 中 MyInterfaceAPI 的 addMyHandler 类实现?

我显然遗漏了一些东西,但我不确定是什么。

【问题讨论】:

    标签: java unit-testing junit mockito


    【解决方案1】:

    您有 2 所学校进行单元测试:伦敦/Mockist 学校和底特律学校。

    如果要使用mock,就必须使用依赖注入,所以可以用mock替换依赖。我认为大多数追随底特律学派的人也会同意这一点,只是因为使用依赖注入“是一件好事”(tm)。

    您可以做的是在构造函数中将ObjA 的实例传递给UnitUnderTest;或者(如果 ObjA 是一个集合)添加方法 UnitUnderTest.addListener(),您可以在其中传递一个处理程序的实例。使用这两种方法,您将注入一个处理程序。

    关于使用 powermock:Powermock 是一种野兽,可以更好地用于单元测试很少且依赖项一团糟的旧项目。如果您现在正在编码,使用 power mock 是错误的(本着公平的精神,这是一个有偏见的想法,但它与许多其他人共享)。

    编辑

    现在我明白你的问题了!而且我认为你试图在一个单元测试中测试太多,这会导致问题。再次,mockist 学校谈论测试交互......这是关键点。所以在UnitUnderTest 的测试中,唯一的交互是与ObjA 设置处理程序,这就是故事的结尾。

    您可能会对ObjA 进行另一次测试,以确保调用所有处理程序。

    现在最后一点是如何测试处理程序的代码。但在此之前,请欣赏每个测试的独立性,因为您正在测试交互(以及代码中的任何逻辑),但不要超过 1 件事。 关于处理程序...您可能不喜欢这样,但是您必须使该类可访问,要么将其公开,要么将其提取到另一个公共类。如果你提取它,你可以放入一个internal 包,这样很明显这个类不应该被其他任何人使用。

    如果您有一个小时的空闲时间,我建议您观看此精彩 演示:Michael Feathers 的 The Deep Synergy Between Testability and Good Design,他在其中介绍了您在代码中的类似示例以及原因把它分开是有意义的。

    【讨论】:

    • 感谢您的回复。我编辑了代码来更正它,objA 实际上已经作为实例传递给了 UnitUnderTest。但是,我仍然不确定如何注入处理程序。有机会在这里请求代码示例吗?
    • 当然...给我 10 分钟 :)
    【解决方案2】:

    使用PowerMockPowerMockito 拦截对addMyHandler 类的调用,该类注入MyInterfaceAPI 的模拟,如Ben Kiefer 关于"PowerMockito: Constructor Mocking" 的教程中所述

    【讨论】:

      【解决方案3】:

      我已经设法让它工作了。在此处发布固定代码以供将来看到此内容的人使用。

      public interface MyInterfaceAPI{
         void fireyMyEvent(String msg);
      }
      

      被测单元:

      public class UnitUnderTest{
      
        private ObjA objA;
        public MyInterfaceAPI interfaceHandler;
      
        public UnitUnderTest(ObjA objA_t) {
           objA = objA_t;
           interfaceHandler = new addMyHandler();
           objA.addMyListener(interfaceHandler); 
        }
      
        class addMyHandler implements MyInterfaceAPI{
          @Override
          public void fireyMyEvent(String msg) {
               System.out.println(msg);
          };
        };
      };
      

      测试:

      public class MyTest {
      
       @org.junit.Test
       public void run() {
      
           ObjA  mockObjA = mock(ObjA .class);    
           UnitUnderTest spyController = Mockito.spy(new UnitUnderTest());
           spyController.hnd.fireyMyEvent("hello from test"); 
       }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-13
        • 1970-01-01
        • 1970-01-01
        • 2010-09-07
        • 2013-10-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多