jmockit中文网 dubbo bean
作者:互联网
Dubbo是我们常用的RPC框架,在写单元测试需要调用Dubbo消费Bean时,如何模拟Dubbo消费Bean的行为呢?
就拿发邮件来说,通常,在代码中,我们是调用邮件的Dubbo服务来完成发送邮件的目的,于是我们会在Spring配置好的发邮件的Dubbo消费Bean,
dubbo-consumer.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<? xml version = "1.0" encoding = "utf-8" ?>
< beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo = "http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
< dubbo:application name = "consumer-of-dubbo-mock-test" />
< dubbo:registry address = "zookeeper://your-zk-address:2181" />
<!-- 生成远程服务代理,可以和本地bean一样使用mailService -->
< dubbo:reference id = "mailService" interface = "cn.jmockit.demos.MailService" />
</ beans >
|
熟悉Dubbo的朋友都知道,上面xml配置是Dubbo的基本配置,配置了dubbo服务的zookeeper地址,还配置了名叫mailService的Dubbo消费Bean,用于在应用程序中发送邮件。
我们在运行单元测试时,如果zookeeper连不上或者mailService的服务提供者不存在,则会导致Spring初始化失败, 而且我们也不希望真正发送邮件(除非是为了测试发送邮件)。于是我们希望对mailService进行Mock。
下面给出一种Mock Dubbo消费Bean的方案:
-
在spring初始化前,对所有Dubbo消费Bean的进行Mock,即<dubbo>标签里的interface都返回本地默认实现。
-
如果想对某几个Dubbo消费Bean进行Mock,则自定义Dubbo消费Bean的实现即可。
请看测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
//dubbo消费bean Mock
@SuppressWarnings ({ "unchecked" , "rawtypes" })
@ContextConfiguration (locations = { "/META-INF/dubbo-consumer.xml" })
@RunWith (SpringJUnit4ClassRunner. class )
public class DubboConsumerBeanMockingTest {
// 这里要@BeforeClass,因为要抢在spring加载dubbo前,对dubbo的消费工厂bean
// ReferenceBean进行mock,不然dubbo可能因为连上不zk或无法找不
// 服务的提供者等原因而无法初始化的,进而,单元测试运行不下去
@BeforeClass
public static void mockDubbo() {
// 你准备mock哪个消费bean
// 比如要对dubbo-consumber.xml里配置的cn.jmockit.demos.MailService这个消费bean进行mock
Map<String, Object> mockMap = new HashMap<String, Object>();
mockMap.put( "cn.jmockit.demos.MailService" , new MockUp(MailService. class ) {
// 在这里书写对这个消费bean进行mock的mock逻辑,想mock哪个方法,就自行添加,注意方法一定要加上@Mock注解哦
@Mock
public boolean sendMail( long userId, String content) {
// 单元测试时,不需要调用邮件服务器发送邮件,这里统一mock邮件发送成功
return true ;
}
}.getMockInstance());
// 如果要Mock其它的消费bean,自行添加,mockMap.put.....如上
new DubboConsumerBeanMockUp(mockMap);
}
// 现在你使用的dubbo消费bean就是本地mock过的了,并不是指向远程dubbo服务的bean了
@Resource
MailService mailService;
@Test
public void testSendMail() {
long userId = 123456 ;
String content = "test mail content" ;
Assert.isTrue(mailService.sendMail(userId, content));
}
}
|
上述代码,最关键的就是DubboConsumerBeanMockUp类了,这个类Mock了所有的Dubbo消费Bean.
源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//dubbo消费bean的MockUp(伪类)
@SuppressWarnings ( "rawtypes" )
public class DubboConsumerBeanMockUp extends MockUp<ReferenceBean> {
// 自定义的消费bean mock对象
private Map<String, Object> mockMap;
public DubboConsumerBeanMockUp() {
}
public DubboConsumerBeanMockUp(Map<String, Object> mockMap) {
this .mockMap = mockMap;
}
// 对ReferenceBean的getObject方法的Mock
@SuppressWarnings ( "unchecked" )
@Mock
public Object getObject(Invocation inv) throws Exception {
ReferenceBean ref = inv.getInvokedInstance();
String interfaceName = ref.getInterface();
Object mock = mockMap.get(interfaceName);
if (mock != null ) {
return mock;
}
return ( new MockUp(Class.forName(interfaceName)) {
}).getMockInstance();
}
}
|
© JMockit中文网 2018 打赏咖啡
标签:jmockit,dubbo,Dubbo,Bean,bean,mock,Mock 来源: https://www.cnblogs.com/funkboy/p/12012551.html