Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用JMockit模拟自动连线接口实现_Java_Spring_Junit_Mocking_Jmockit - Fatal编程技术网

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

Java 使用JMockit模拟自动连线接口实现,java,spring,junit,mocking,jmockit,Java,Spring,Junit,Mocking,Jmockit,我们正在为一个类编写JUnit测试,该类使用Spring自动连接来注入依赖项,该依赖项是接口的某个实例。由于被测试的类从未显式地实例化依赖项或将其传递到构造函数中,因此JMockit似乎也没有义务实例化它 到目前为止,我们一直在使用SpringRunner为我们提供Spring负载模拟依赖项,这很有效。我们不喜欢的两件事是:1)每次运行测试时都必须加载和初始化Spring框架,这不是很快;2)我们被迫显式地将所有模拟依赖项创建为真实类,这是JMockit帮助消除的 下面是我们正在测试的一个简化示

我们正在为一个类编写JUnit测试,该类使用Spring自动连接来注入依赖项,该依赖项是接口的某个实例。由于被测试的类从未显式地实例化依赖项或将其传递到构造函数中,因此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

您可以使用
org.springframework.test.util.ReflectionTestUtils
在您的测试用例中显式地注入模拟的
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
   }
}
@Component
public class AClass {

   @Autowired
   private Bean1 bean1;

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

mockit.Deencapsulation
是一个基于反射的实用程序类,它允许您调用私有方法、get/set字段等。

并提供上述提示,作为一个对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 );
}
@之前
公共作废设置(){
IMarketMakerDal theMock=新模型(){
@嘲弄
MarketMakerDcl FindByMarketMarkerGuid(字符串marketMakerGuid){
MarketMakerDcl MarketMakerDcl=新的MarketMakerDcl();
marketMakerDcl.setBaseCurrencyCode(货币代码美元);
返回市场makerdcl;
}
}.getMockInstance();
设置字段(测试中的单元,模块);
}

谢谢大家的帮助。

感谢那些遇到的人

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

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

  • 使用
    @Tested(fullyInitialized=true)
    而不是
    @Tested
  • 将jmockit的版本恢复到
    1.18
    或以前的版本

  • 如果接口有@Qualifier注释,则需要将@Injectable字段的名称与Qualifier中的名称完全相同

    以下是引自:

    在查找匹配的@Injectable或@Tested值时,将使用来自JavaEE(@Resource(name),@Named)或Spring框架(@Qualifier)的字段注释中指定的自定义名称。当该名称包含-(破折号)或时。(点)字符,则使用相应的大小写名称

    例如:

    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
       }
    }
    
    @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();
    }
    

    另外,对于每个@autowiredbean,也不需要使用setfield,当@Tested类实例化时,所有字段都会自动注入。在JMockit版本上测试。1.30

    另请参见:这确实是一门有用的课程。尽管如此,必须显式地创建mock还是挫败了首先使用JMockit的主要原因之一。这非常有用。我手工创建mock,并且在测试的类中有一个autowired属性。这允许我将测试中的属性设置为mock,而无需编辑测试中的代码!很好。请注意:自从这个答案发布以来,JMockit增加了对模拟对象自动注入测试类的支持。在本例中,将
    @Autowired
    替换为
    @Tested
    ,将
    @mock
    替换为
    @Injectable
    。哇@Rogério!太好了!JMockit是如此强大。。。我很喜欢@Rogério jmockit coverage tool可以为mockito生成报告吗?我们的遗留测试代码使用mockito。任何链接都是有用的。@yuyue007是的,覆盖工具不需要jmockit.jar的存在,尽管它存在时会更容易。您需要使用“-javaagent:jmockit coverage.jar”JVM初始化参数(来自命令行/IDE或Ant/Maven/Gradle构建脚本)。细节在这里。@Rogério Cool!我在使用泛型类型的cascade-mock时遇到了一些问题,我在github中创建了一个问题,您是否可以帮助检查哪里出错,或者这是否是一个bug。非常感谢。