Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
superrain51
apollo
提交
2c4800f4
apollo
项目概览
superrain51
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
apollo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2c4800f4
编写于
8月 22, 2018
作者:
Z
zhangzheng
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add apollo mockserver
(cherry picked from commit 9de272b)
上级
44a6a7d2
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
372 addition
and
0 deletion
+372
-0
apollo-mockserver/pom.xml
apollo-mockserver/pom.xml
+38
-0
apollo-mockserver/src/main/java/com/ctrip/framework/apollo/mockserver/EmbeddedApollo.java
...com/ctrip/framework/apollo/mockserver/EmbeddedApollo.java
+159
-0
apollo-mockserver/src/test/java/com/ctrip/framework/apollo/mockserver/ApolloMockServerTest.java
...rip/framework/apollo/mockserver/ApolloMockServerTest.java
+91
-0
apollo-mockserver/src/test/java/com/ctrip/framework/apollo/mockserver/SpringIntegrationTest.java
...ip/framework/apollo/mockserver/SpringIntegrationTest.java
+80
-0
apollo-mockserver/src/test/resources/mockdata-application.properties
...server/src/test/resources/mockdata-application.properties
+2
-0
apollo-mockserver/src/test/resources/mockdata-othernamespace.properties
...ver/src/test/resources/mockdata-othernamespace.properties
+2
-0
未找到文件。
apollo-mockserver/pom.xml
0 → 100644
浏览文件 @
2c4800f4
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<parent>
<artifactId>
apollo
</artifactId>
<groupId>
com.ctrip.framework.apollo
</groupId>
<version>
1.1.5-SNAPSHOT
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
apollo-mockserver
</artifactId>
<dependencies>
<dependency>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo-client
</artifactId>
<version>
${project.version}
</version>
</dependency>
<dependency>
<groupId>
com.squareup.okhttp3
</groupId>
<artifactId>
mockwebserver
</artifactId>
<version>
3.11.0
</version>
</dependency>
<dependency>
<groupId>
com.squareup.okhttp3
</groupId>
<artifactId>
okhttp
</artifactId>
<version>
3.11.0
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter
</artifactId>
<version>
1.3.8.RELEASE
</version>
<scope>
provided
</scope>
</dependency>
</dependencies>
</project>
apollo-mockserver/src/main/java/com/ctrip/framework/apollo/mockserver/EmbeddedApollo.java
0 → 100644
浏览文件 @
2c4800f4
package
com.ctrip.framework.apollo.mockserver
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfig
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfigNotification
;
import
com.ctrip.framework.apollo.core.dto.ServiceDTO
;
import
com.ctrip.framework.apollo.core.utils.ResourceUtils
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.ImmutableSet
;
import
com.google.gson.Gson
;
import
com.google.gson.reflect.TypeToken
;
import
java.io.IOException
;
import
java.lang.reflect.Type
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Properties
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
okhttp3.mockwebserver.Dispatcher
;
import
okhttp3.mockwebserver.MockResponse
;
import
okhttp3.mockwebserver.MockWebServer
;
import
okhttp3.mockwebserver.RecordedRequest
;
import
org.junit.rules.ExternalResource
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* Create by zhangzheng on 8/22/18
* Email:zhangzheng@youzan.com
*/
public
class
EmbeddedApollo
extends
ExternalResource
{
private
Gson
gson
=
new
Gson
();
private
Logger
logger
=
LoggerFactory
.
getLogger
(
EmbeddedApollo
.
class
);
private
Type
notificationType
=
new
TypeToken
<
List
<
ApolloConfigNotification
>>(){}.
getType
();
private
String
listenningUrl
;
private
MockWebServer
server
;
@Override
protected
void
before
()
throws
Throwable
{
server
=
new
MockWebServer
();
final
Dispatcher
dispatcher
=
new
Dispatcher
()
{
@Override
public
MockResponse
dispatch
(
RecordedRequest
request
)
throws
InterruptedException
{
if
(
request
.
getPath
().
startsWith
(
"/services/config"
))
{
return
new
MockResponse
().
setResponseCode
(
200
)
.
setBody
(
mockConfigServiceAddr
(
listenningUrl
));
}
else
if
(
request
.
getPath
().
startsWith
(
"/notifications/v2"
))
{
String
notifications
=
request
.
getRequestUrl
().
queryParameter
(
"notifications"
);
MockResponse
response
=
new
MockResponse
().
setResponseCode
(
200
).
setBody
(
mockLongPollBody
(
notifications
));
return
response
;
}
else
if
(
request
.
getPath
().
startsWith
(
"/configs"
))
{
List
<
String
>
pathSegments
=
request
.
getRequestUrl
().
pathSegments
();
String
appId
=
pathSegments
.
get
(
1
);
String
cluster
=
pathSegments
.
get
(
2
);
String
namespace
=
pathSegments
.
get
(
3
);
return
new
MockResponse
().
setResponseCode
(
200
)
.
setBody
(
loadConfigFor
(
namespace
));
}
return
new
MockResponse
().
setResponseCode
(
404
);
}
};
server
.
setDispatcher
(
dispatcher
);
server
.
start
();
//指定apollo的metaserver地址为localhost
int
port
=
server
.
getPort
();
this
.
listenningUrl
=
"http://localhost:"
+
port
;
System
.
setProperty
(
"apollo.env"
,
"mock"
);
System
.
setProperty
(
"mock_meta"
,
listenningUrl
);
System
.
setProperty
(
"apollo.longPollingInitialDelayInMills"
,
"1"
);
super
.
before
();
}
@Override
protected
void
after
()
{
try
{
server
.
close
();
}
catch
(
IOException
e
)
{
logger
.
error
(
"stop apollo server error"
,
e
);
}
}
private
String
loadConfigFor
(
String
namespace
){
String
filename
=
String
.
format
(
"mockdata-%s.properties"
,
namespace
);
final
Properties
prop
=
ResourceUtils
.
readConfigFile
(
filename
,
new
Properties
());
Map
<
String
,
String
>
configurations
=
prop
.
stringPropertyNames
().
stream
().
collect
(
Collectors
.
toMap
(
key
->
key
,
key
->
prop
.
getProperty
(
key
)));
ApolloConfig
apolloConfig
=
new
ApolloConfig
(
"someAppId"
,
"someCluster"
,
namespace
,
"someReleaseKey"
);
Map
<
String
,
String
>
mergedConfigurations
=
mergeModifyByUser
(
namespace
,
configurations
);
apolloConfig
.
setConfigurations
(
mergedConfigurations
);
return
gson
.
toJson
(
apolloConfig
);
}
private
String
mockLongPollBody
(
String
notificationsStr
){
List
<
ApolloConfigNotification
>
oldNotifications
=
gson
.
fromJson
(
notificationsStr
,
notificationType
);
List
<
ApolloConfigNotification
>
newNotifications
=
new
ArrayList
<>();
for
(
ApolloConfigNotification
noti:
oldNotifications
){
newNotifications
.
add
(
new
ApolloConfigNotification
(
noti
.
getNamespaceName
(),
noti
.
getNotificationId
()+
1
));
}
return
gson
.
toJson
(
newNotifications
);
}
private
String
mockConfigServiceAddr
(
String
addr
){
ServiceDTO
serviceDTO
=
new
ServiceDTO
();
serviceDTO
.
setAppName
(
"someAppName"
);
serviceDTO
.
setInstanceId
(
"someInstanceId"
);
serviceDTO
.
setHomepageUrl
(
addr
);
return
gson
.
toJson
(
Arrays
.
asList
(
serviceDTO
));
}
/**
* 合并用户对namespace的修改
* @param configurations
* @return
*/
private
Map
<
String
,
String
>
mergeModifyByUser
(
String
namespace
,
Map
<
String
,
String
>
configurations
){
if
(
addedPropertyOfNamespace
.
containsKey
(
namespace
)){
configurations
.
putAll
(
addedPropertyOfNamespace
.
get
(
namespace
));
}
if
(
deletedKeysOfNamespace
.
containsKey
(
namespace
)){
for
(
String
k:
deletedKeysOfNamespace
.
get
(
namespace
)){
configurations
.
remove
(
k
);
}
}
return
configurations
;
}
private
Map
<
String
,
Map
<
String
,
String
>>
addedPropertyOfNamespace
=
new
HashMap
<>();
public
void
addOrModifyPropery
(
String
namespace
,
String
someKey
,
String
someValue
)
{
if
(
addedPropertyOfNamespace
.
containsKey
(
namespace
)){
addedPropertyOfNamespace
.
get
(
namespace
).
put
(
someKey
,
someValue
);
}
else
{
addedPropertyOfNamespace
.
put
(
namespace
,
ImmutableMap
.
of
(
someKey
,
someValue
));
}
}
private
Map
<
String
,
Set
<
String
>>
deletedKeysOfNamespace
=
new
HashMap
<>();
public
void
delete
(
String
namespace
,
String
someKey
)
{
if
(
deletedKeysOfNamespace
.
containsKey
(
namespace
)){
deletedKeysOfNamespace
.
get
(
namespace
).
add
(
someKey
);
}
else
{
deletedKeysOfNamespace
.
put
(
namespace
,
ImmutableSet
.
of
(
someKey
));
}
}
}
apollo-mockserver/src/test/java/com/ctrip/framework/apollo/mockserver/ApolloMockServerTest.java
0 → 100644
浏览文件 @
2c4800f4
package
com.ctrip.framework.apollo.mockserver
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigChangeListener
;
import
com.ctrip.framework.apollo.ConfigService
;
import
com.ctrip.framework.apollo.enums.PropertyChangeType
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
import
com.google.common.util.concurrent.SettableFuture
;
import
java.io.IOException
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeoutException
;
import
org.junit.AfterClass
;
import
org.junit.BeforeClass
;
import
org.junit.ClassRule
;
import
org.junit.Test
;
import
org.mockito.InjectMocks
;
import
org.springframework.boot.test.WebIntegrationTest
;
/**
* Create by zhangzheng on 8/10/18
* Email:zhangzheng@youzan.com
*/
public
class
ApolloMockServerTest
{
@ClassRule
public
static
EmbeddedApollo
embeddedApollo
=
new
EmbeddedApollo
();
@Test
public
void
testPropertyInject
()
{
String
namespace
=
"application"
;
Config
config
=
ConfigService
.
getConfig
(
namespace
);
assertEquals
(
"value1"
,
config
.
getProperty
(
"key1"
,
""
));
assertEquals
(
"value2"
,
config
.
getProperty
(
"key2"
,
""
));
String
otherNamespace
=
"othernamespace"
;
config
=
ConfigService
.
getConfig
(
otherNamespace
);
assertEquals
(
"othervalue1"
,
config
.
getProperty
(
"key1"
,
""
));
assertEquals
(
"othervalue2"
,
config
.
getProperty
(
"key2"
,
""
));
}
@Test
public
void
testListennerTriggeredByAdd
()
throws
InterruptedException
,
ExecutionException
,
TimeoutException
{
System
.
setProperty
(
"apollo.longPollingInitialDelayInMills"
,
"1"
);
String
someNamespace
=
"application"
;
Config
config
=
ConfigService
.
getConfig
(
someNamespace
);
SettableFuture
<
Boolean
>
changed
=
SettableFuture
.
create
();
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
config
.
addChangeListener
(
new
ConfigChangeListener
()
{
@Override
public
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
assertEquals
(
true
,
changeEvent
.
isChanged
(
someKey
));
assertEquals
(
someValue
,
changeEvent
.
getChange
(
someKey
).
getNewValue
());
changed
.
set
(
true
);
}
});
embeddedApollo
.
addOrModifyPropery
(
someNamespace
,
someKey
,
someValue
);
assertEquals
(
true
,
changed
.
get
(
1000
,
TimeUnit
.
MILLISECONDS
));
}
@Test
public
void
testListennerTriggeredByDel
()
throws
InterruptedException
,
ExecutionException
,
TimeoutException
{
String
someNamespace
=
"application"
;
Config
config
=
ConfigService
.
getConfig
(
someNamespace
);
SettableFuture
<
Boolean
>
changed
=
SettableFuture
.
create
();
String
someKey
=
"key1"
;
config
.
addChangeListener
(
new
ConfigChangeListener
()
{
@Override
public
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
assertEquals
(
true
,
changeEvent
.
isChanged
(
someKey
));
assertEquals
(
PropertyChangeType
.
DELETED
,
changeEvent
.
getChange
(
someKey
).
getChangeType
());
changed
.
set
(
true
);
}
});
embeddedApollo
.
delete
(
someNamespace
,
someKey
);
assertEquals
(
true
,
changed
.
get
(
1000
,
TimeUnit
.
MILLISECONDS
));
}
}
apollo-mockserver/src/test/java/com/ctrip/framework/apollo/mockserver/SpringIntegrationTest.java
0 → 100644
浏览文件 @
2c4800f4
package
com.ctrip.framework.apollo.mockserver
;
import
com.ctrip.framework.apollo.mockserver.SpringIntegrationTest.TestConfiguration
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
import
com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener
;
import
com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig
;
import
static
org
.
junit
.
Assert
.*;
import
com.google.common.util.concurrent.SettableFuture
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeoutException
;
import
org.junit.ClassRule
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.test.SpringApplicationConfiguration
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
;
/**
* Create by zhangzheng on 8/16/18
* Email:zhangzheng@youzan.com
*/
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@SpringApplicationConfiguration
(
classes
=
TestConfiguration
.
class
)
public
class
SpringIntegrationTest
{
@Autowired
TestBean
testBean
;
@ClassRule
public
static
EmbeddedApollo
embeddedApollo
=
new
EmbeddedApollo
();
@Test
public
void
testPropertyInjectAndListener
()
throws
InterruptedException
,
ExecutionException
,
TimeoutException
{
assertEquals
(
"value1"
,
testBean
.
key1
);
assertEquals
(
"value2"
,
testBean
.
key2
);
String
otherNamespace
=
"othernamespace"
;
embeddedApollo
.
addOrModifyPropery
(
otherNamespace
,
"someKey"
,
"someValue"
);
ConfigChangeEvent
changeEvent
=
testBean
.
futureData
.
get
(
5000
,
TimeUnit
.
MILLISECONDS
);
assertEquals
(
otherNamespace
,
changeEvent
.
getNamespace
());
assertEquals
(
"someValue"
,
changeEvent
.
getChange
(
"someKey"
).
getNewValue
());
}
@EnableApolloConfig
(
"application"
)
@Configuration
static
class
TestConfiguration
{
@Bean
public
TestBean
testBean
(){
return
new
TestBean
();
}
}
static
class
TestBean
{
@Value
(
"${key1:default}"
)
String
key1
;
@Value
(
"${key2:default}"
)
String
key2
;
SettableFuture
<
ConfigChangeEvent
>
futureData
=
SettableFuture
.
create
();
@ApolloConfigChangeListener
(
"othernamespace"
)
private
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
futureData
.
set
(
changeEvent
);
}
}
}
apollo-mockserver/src/test/resources/mockdata-application.properties
0 → 100644
浏览文件 @
2c4800f4
key1
=
value1
key2
=
value2
apollo-mockserver/src/test/resources/mockdata-othernamespace.properties
0 → 100644
浏览文件 @
2c4800f4
key1
=
othervalue1
key2
=
othervalue2
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录