11

我们正在为一个使用 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 创建一个 mock someInterface

4

5 回答 5

12

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是一个基于反射的实用程序类,可让您调用私有方法、获取/设置字段等。

于 2010-01-02T17:08:41.597 回答
8

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

查看文档

于 2009-12-30T15:17:27.173 回答
4

有了上面提供的提示,我发现作为 JMockit 的新手最有用的是: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 );
}

感谢大家的帮助。

于 2010-01-03T15:41:08.380 回答
3

对于那些遇见的人

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

或者

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

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

  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

于 2016-11-01T09:57:01.700 回答
2

如果您有接口的@Qualifier 注释,则需要完全按照限定符中的名称命名您的@Injectable 字段。

这是来自JMockit doc的引用:

在查找匹配的 @Injectable 或 @Tested 值时,使用来自 Java EE(@Resource(name)、@Named)或 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 版本上测试。1.30

于 2017-02-22T21:32:56.580 回答