繁体   English   中英

使用JMockit模拟自动连接的接口实现

[英]Using JMockit to mock autowired interface implementations

我们正在为一个使用Spring自动装配注入依赖关系的类编写JUnit测试,该依赖关系是一个接口实例。 由于被测试的类永远不会显式地实例化依赖项或者它在构造函数中传递,因此看起来JMockit也没有义务实例化它。

到目前为止,我们一直在使用SpringRunner为我们提供Spring加载模拟依赖项,这是有效的。 我们不喜欢的两件事是:1)每次运行测试时都必须加载和初始化Spring框架,这不是非常快速的; 2)我们被迫显式创建所有模拟依赖项作为真正的类, JMockit有助于消除。

这是我们测试的简化示例:

public class UnitUnderTest {

   @Autowired
   ISomeInterface someInterface;

   public void callInterfaceMethod() {

      System.out.println( "UnitUnderTest.callInterfaceMethod calling someInterface.doSomething");
      someInterface.doSomething();
   }

}

所以,问题是,有没有办法让JMockit创建一个模拟someInterface

JMockit将始终实例化一个模拟接口(最终模拟字段除外),但这只发生在测试代码中。 它不会自动将实例注入到测试代码中。

您必须手动注入模拟实例。 例如:

public class SomeTest
{
   @Autowired UnitUnderTest unitUnderTest;
   @Mocked ISomeInterface theMock; // created and assigned automatically

   @Test
   public void testSomeMethod()
   {
      Deencapsulation.setField(unitUnderTest, theMock);
      //proceed with unit test here
   }
}

mockit.Deencapsulation是一个基于反射的实用程序类,允许您调用私有方法,获取/设置字段等。

您可以使用org.springframework.test.util.ReflectionTestUtils在测试用例中显式注入ISomeInterface

文档

通过上面提供的提示,这里是我发现最有用的JMockit Deencapsulation :JMockit提供了Deencapsulation类,允许您设置私有依赖字段的值(不需要拖动Spring库)和MockUp允许您显式创建接口实现并模拟接口的一个或多个方法的类。 以下是我最终解决这个特殊情况的方法:

@Before
public void setUp() {

   IMarketMakerDal theMock = new MockUp <IMarketMakerDal>() {

      @Mock
      MarketMakerDcl findByMarketMakerGuid( String marketMakerGuid ) {

         MarketMakerDcl marketMakerDcl = new MarketMakerDcl();
         marketMakerDcl.setBaseCurrencyCode( CURRENCY_CODE_US_DOLLAR );
         return marketMakerDcl;
      }
   }.getMockInstance();

   setField( unitUnderTest, theMock );
}

谢谢大家的帮助。

对于那些见过面的人

java.lang.IllegalStateException: Missing @Injectable for field *** 

要么

java.lang.IllegalStateException: Missing @Tested class for field ***

使用jmockitspring (或spring boot )框架中模拟@autowired字段时出错,我在下面两步做了以避免上述错误:

  1. 使用@Tested(fullyInitialized=true)而不是@Tested

https://groups.google.com/forum/#!msg/jmockit-users/uo0S51lSX24/lQhLNN--eJcJ

  1. 将jmockit的版本恢复为1.18或之前的版本

https://groups.google.com/forum/#!topic/jmockit-users/wMFZggsA8LM

如果您有接口的@Qualifier注释,则需要将@Injectable字段命名为与限定符中命名的字段完全相同。

以下是JMockit doc的引用:

在查找匹配的@Injectable或@Tested值时,将使用在Java EE(@Resource(name),@ Name)或Spring框架(@Qualifier)的字段注释中指定的自定义名称。 当这样的名字包含 - (短划线)或。 (点)字符,相反使用相应的驼峰名称。

例如:

@Component
public class AClass {

   @Autowired
   private Bean1 bean1;

   @Autowired
   @Qualifier("my-dashed-name")
   private AmqpTemplate rpcTemplate;
}

单元测试类:

public class AClassTest {

   @Injectable
   private Bean1 bean1;

   @Injectable
   private AmqpTemplate myDashedName;

   @Tested
   private AClass aClass = new AClass();
}

此外,不需要为每个@Autowired bean使用setFiled,所有字段在@Tested类实例化时自动注入。 在JMockit ver上测试过。 1.30

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM