Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wd1105040417
retrofit
提交
d1782df6
R
retrofit
项目概览
wd1105040417
/
retrofit
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
retrofit
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
d1782df6
编写于
12月 05, 2015
作者:
J
Jesse Wilson
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1343 from square/jw/new-mock
Introduce new mock pattern with a behavior delegate.
上级
2ea316cd
16504420
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
117 addition
and
449 deletion
+117
-449
retrofit-adapters/pom.xml
retrofit-adapters/pom.xml
+0
-1
retrofit-adapters/rxjava-mock/pom.xml
retrofit-adapters/rxjava-mock/pom.xml
+0
-48
retrofit-adapters/rxjava-mock/src/main/java/retrofit2/mock/RxJavaBehaviorAdapter.java
...k/src/main/java/retrofit2/mock/RxJavaBehaviorAdapter.java
+0
-56
retrofit-adapters/rxjava-mock/src/main/java/retrofit2/mock/SingleHelper.java
...xjava-mock/src/main/java/retrofit2/mock/SingleHelper.java
+0
-39
retrofit-adapters/rxjava-mock/src/test/java/retrofit2/mock/RxJavaBehaviorAdapterTest.java
...c/test/java/retrofit2/mock/RxJavaBehaviorAdapterTest.java
+0
-182
retrofit-mock/src/main/java/retrofit2/mock/BehaviorCall.java
retrofit-mock/src/main/java/retrofit2/mock/BehaviorCall.java
+7
-34
retrofit-mock/src/main/java/retrofit2/mock/BehaviorDelegate.java
...t-mock/src/main/java/retrofit2/mock/BehaviorDelegate.java
+64
-0
retrofit-mock/src/main/java/retrofit2/mock/CallBehaviorAdapter.java
...ock/src/main/java/retrofit2/mock/CallBehaviorAdapter.java
+0
-40
retrofit-mock/src/main/java/retrofit2/mock/MockRetrofit.java
retrofit-mock/src/main/java/retrofit2/mock/MockRetrofit.java
+22
-21
retrofit-mock/src/test/java/retrofit2/mock/MockRetrofitTest.java
...t-mock/src/test/java/retrofit2/mock/MockRetrofitTest.java
+8
-9
samples/src/main/java/com/example/retrofit/SimpleMockService.java
...src/main/java/com/example/retrofit/SimpleMockService.java
+16
-19
未找到文件。
retrofit-adapters/pom.xml
浏览文件 @
d1782df6
...
...
@@ -16,6 +16,5 @@
<modules>
<module>
rxjava
</module>
<module>
rxjava-mock
</module>
</modules>
</project>
retrofit-adapters/rxjava-mock/pom.xml
已删除
100644 → 0
浏览文件 @
2ea316cd
<?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/maven-v4_0_0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
com.squareup.retrofit2
</groupId>
<artifactId>
retrofit-adapters
</artifactId>
<version>
2.0.0-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<artifactId>
adapter-rxjava-mock
</artifactId>
<name>
Adapter: RxJava Mock
</name>
<dependencies>
<dependency>
<groupId>
${project.groupId}
</groupId>
<artifactId>
retrofit
</artifactId>
<version>
${project.version}
</version>
</dependency>
<dependency>
<groupId>
${project.groupId}
</groupId>
<artifactId>
retrofit-mock
</artifactId>
<version>
${project.version}
</version>
</dependency>
<dependency>
<groupId>
${project.groupId}
</groupId>
<artifactId>
adapter-rxjava
</artifactId>
<version>
${project.version}
</version>
</dependency>
<dependency>
<groupId>
io.reactivex
</groupId>
<artifactId>
rxjava
</artifactId>
</dependency>
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.assertj
</groupId>
<artifactId>
assertj-core
</artifactId>
<scope>
test
</scope>
</dependency>
</dependencies>
</project>
retrofit-adapters/rxjava-mock/src/main/java/retrofit2/mock/RxJavaBehaviorAdapter.java
已删除
100644 → 0
浏览文件 @
2ea316cd
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
retrofit2.mock
;
import
rx.Observable
;
import
rx.functions.Func1
;
import
static
java
.
util
.
concurrent
.
TimeUnit
.
MILLISECONDS
;
public
final
class
RxJavaBehaviorAdapter
implements
NetworkBehavior
.
Adapter
<
Object
>
{
public
static
RxJavaBehaviorAdapter
create
()
{
return
new
RxJavaBehaviorAdapter
();
}
private
RxJavaBehaviorAdapter
()
{
}
@Override
public
Object
applyBehavior
(
NetworkBehavior
behavior
,
Object
value
)
{
if
(
value
instanceof
Observable
)
{
return
applyObservableBehavior
(
behavior
,
(
Observable
<?>)
value
);
}
String
name
=
value
.
getClass
().
getCanonicalName
();
if
(
"rx.Single"
.
equals
(
name
))
{
// Apply behavior to the Single from a separate class. This defers classloading such that
// regular Observable operation can be leveraged without relying on this unstable RxJava API.
return
SingleHelper
.
applySingleBehavior
(
behavior
,
value
);
}
throw
new
IllegalStateException
(
"Unsupported type "
+
name
);
}
public
Observable
<?>
applyObservableBehavior
(
final
NetworkBehavior
behavior
,
final
Observable
<?>
value
)
{
return
Observable
.
timer
(
behavior
.
calculateDelay
(
MILLISECONDS
),
MILLISECONDS
)
.
flatMap
(
new
Func1
<
Long
,
Observable
<?>>()
{
@Override
public
Observable
<?>
call
(
Long
ignored
)
{
if
(
behavior
.
calculateIsFailure
())
{
return
Observable
.
error
(
behavior
.
failureException
());
}
return
value
;
}
});
}
}
retrofit-adapters/rxjava-mock/src/main/java/retrofit2/mock/SingleHelper.java
已删除
100644 → 0
浏览文件 @
2ea316cd
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
retrofit2.mock
;
import
rx.Observable
;
import
rx.Single
;
import
rx.functions.Func1
;
import
static
java
.
util
.
concurrent
.
TimeUnit
.
MILLISECONDS
;
final
class
SingleHelper
{
@SuppressWarnings
(
"unchecked"
)
// Caller must instanceof / getClass() verify 'value' is Single.
public
static
Object
applySingleBehavior
(
final
NetworkBehavior
behavior
,
Object
value
)
{
final
Single
<
Object
>
single
=
(
Single
<
Object
>)
value
;
return
Observable
.
timer
(
behavior
.
calculateDelay
(
MILLISECONDS
),
MILLISECONDS
)
.
flatMap
(
new
Func1
<
Long
,
Observable
<?>>()
{
@Override
public
Observable
<?>
call
(
Long
ignored
)
{
if
(
behavior
.
calculateIsFailure
())
{
return
Observable
.
error
(
behavior
.
failureException
());
}
return
single
.
toObservable
();
}
})
.
toSingle
();
}
}
retrofit-adapters/rxjava-mock/src/test/java/retrofit2/mock/RxJavaBehaviorAdapterTest.java
已删除
100644 → 0
浏览文件 @
2ea316cd
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
retrofit2.mock
;
import
java.util.Random
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicLong
;
import
java.util.concurrent.atomic.AtomicReference
;
import
org.junit.Before
;
import
org.junit.Test
;
import
rx.Observable
;
import
rx.Single
;
import
rx.Subscriber
;
import
static
java
.
util
.
concurrent
.
TimeUnit
.
MILLISECONDS
;
import
static
java
.
util
.
concurrent
.
TimeUnit
.
SECONDS
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
public
final
class
RxJavaBehaviorAdapterTest
{
interface
DoWorkService
{
Observable
<
String
>
observableResponse
();
Single
<
String
>
singleResponse
();
}
private
final
NetworkBehavior
behavior
=
NetworkBehavior
.
create
(
new
Random
(
2847
));
private
DoWorkService
service
;
@Before
public
void
setUp
()
{
DoWorkService
mockService
=
new
DoWorkService
()
{
@Override
public
Observable
<
String
>
observableResponse
()
{
return
Observable
.
just
(
"Hi!"
);
}
@Override
public
Single
<
String
>
singleResponse
()
{
return
Single
.
just
(
"Hi!"
);
}
};
NetworkBehavior
.
Adapter
<?>
adapter
=
RxJavaBehaviorAdapter
.
create
();
MockRetrofit
mockRetrofit
=
new
MockRetrofit
(
behavior
,
adapter
);
service
=
mockRetrofit
.
create
(
DoWorkService
.
class
,
mockService
);
}
@Test
public
void
observableFailureAfterDelay
()
throws
InterruptedException
{
behavior
.
setDelay
(
100
,
MILLISECONDS
);
behavior
.
setVariancePercent
(
0
);
behavior
.
setFailurePercent
(
100
);
Observable
<
String
>
observable
=
service
.
observableResponse
();
final
long
startNanos
=
System
.
nanoTime
();
final
AtomicLong
tookMs
=
new
AtomicLong
();
final
AtomicReference
<
Throwable
>
failureRef
=
new
AtomicReference
<>();
final
CountDownLatch
latch
=
new
CountDownLatch
(
1
);
observable
.
subscribe
(
new
Subscriber
<
String
>()
{
@Override
public
void
onNext
(
String
s
)
{
throw
new
AssertionError
();
}
@Override
public
void
onError
(
Throwable
throwable
)
{
tookMs
.
set
(
TimeUnit
.
NANOSECONDS
.
toMillis
(
System
.
nanoTime
()
-
startNanos
));
failureRef
.
set
(
throwable
);
latch
.
countDown
();
}
@Override
public
void
onCompleted
()
{
}
});
assertTrue
(
latch
.
await
(
1
,
SECONDS
));
assertThat
(
failureRef
.
get
()).
isSameAs
(
behavior
.
failureException
());
assertThat
(
tookMs
.
get
()).
isGreaterThanOrEqualTo
(
100
);
}
@Test
public
void
observableSuccessAfterDelay
()
throws
InterruptedException
{
behavior
.
setDelay
(
100
,
MILLISECONDS
);
behavior
.
setVariancePercent
(
0
);
behavior
.
setFailurePercent
(
0
);
Observable
<
String
>
observable
=
service
.
observableResponse
();
final
long
startNanos
=
System
.
nanoTime
();
final
AtomicLong
tookMs
=
new
AtomicLong
();
final
AtomicReference
<
String
>
actual
=
new
AtomicReference
<>();
final
CountDownLatch
latch
=
new
CountDownLatch
(
1
);
observable
.
subscribe
(
new
Subscriber
<
String
>()
{
@Override
public
void
onNext
(
String
value
)
{
tookMs
.
set
(
TimeUnit
.
NANOSECONDS
.
toMillis
(
System
.
nanoTime
()
-
startNanos
));
actual
.
set
(
value
);
latch
.
countDown
();
}
@Override
public
void
onError
(
Throwable
throwable
)
{
throw
new
AssertionError
();
}
@Override
public
void
onCompleted
()
{
}
});
assertTrue
(
latch
.
await
(
1
,
SECONDS
));
assertThat
(
actual
.
get
()).
isEqualTo
(
"Hi!"
);
assertThat
(
tookMs
.
get
()).
isGreaterThanOrEqualTo
(
100
);
}
@Test
public
void
singleFailureAfterDelay
()
throws
InterruptedException
{
behavior
.
setDelay
(
100
,
MILLISECONDS
);
behavior
.
setVariancePercent
(
0
);
behavior
.
setFailurePercent
(
100
);
Single
<
String
>
observable
=
service
.
singleResponse
();
final
long
startNanos
=
System
.
nanoTime
();
final
AtomicLong
tookMs
=
new
AtomicLong
();
final
AtomicReference
<
Throwable
>
failureRef
=
new
AtomicReference
<>();
final
CountDownLatch
latch
=
new
CountDownLatch
(
1
);
observable
.
subscribe
(
new
Subscriber
<
String
>()
{
@Override
public
void
onNext
(
String
s
)
{
throw
new
AssertionError
();
}
@Override
public
void
onError
(
Throwable
throwable
)
{
tookMs
.
set
(
TimeUnit
.
NANOSECONDS
.
toMillis
(
System
.
nanoTime
()
-
startNanos
));
failureRef
.
set
(
throwable
);
latch
.
countDown
();
}
@Override
public
void
onCompleted
()
{
}
});
assertTrue
(
latch
.
await
(
1
,
SECONDS
));
assertThat
(
failureRef
.
get
()).
isSameAs
(
behavior
.
failureException
());
assertThat
(
tookMs
.
get
()).
isGreaterThanOrEqualTo
(
100
);
}
@Test
public
void
singleSuccessAfterDelay
()
throws
InterruptedException
{
behavior
.
setDelay
(
100
,
MILLISECONDS
);
behavior
.
setVariancePercent
(
0
);
behavior
.
setFailurePercent
(
0
);
Single
<
String
>
observable
=
service
.
singleResponse
();
final
long
startNanos
=
System
.
nanoTime
();
final
AtomicLong
tookMs
=
new
AtomicLong
();
final
AtomicReference
<
String
>
actual
=
new
AtomicReference
<>();
final
CountDownLatch
latch
=
new
CountDownLatch
(
1
);
observable
.
subscribe
(
new
Subscriber
<
String
>()
{
@Override
public
void
onNext
(
String
value
)
{
tookMs
.
set
(
TimeUnit
.
NANOSECONDS
.
toMillis
(
System
.
nanoTime
()
-
startNanos
));
actual
.
set
(
value
);
latch
.
countDown
();
}
@Override
public
void
onError
(
Throwable
throwable
)
{
throw
new
AssertionError
();
}
@Override
public
void
onCompleted
()
{
}
});
assertTrue
(
latch
.
await
(
1
,
SECONDS
));
assertThat
(
actual
.
get
()).
isEqualTo
(
"Hi!"
);
assertThat
(
tookMs
.
get
()).
isGreaterThanOrEqualTo
(
100
);
}
}
retrofit-mock/src/main/java/retrofit2/mock/BehaviorCall.java
浏览文件 @
d1782df6
...
...
@@ -18,7 +18,6 @@ package retrofit2.mock;
import
java.io.IOException
;
import
java.io.InterruptedIOException
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.Executor
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.atomic.AtomicReference
;
...
...
@@ -31,31 +30,21 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
final
class
BehaviorCall
<
T
>
implements
Call
<
T
>
{
private
final
NetworkBehavior
behavior
;
private
final
ExecutorService
backgroundExecutor
;
private
final
Executor
callbackExecutor
;
private
final
Call
<
T
>
delegate
;
private
volatile
Future
<?>
task
;
private
volatile
boolean
canceled
;
private
volatile
boolean
executed
;
BehaviorCall
(
NetworkBehavior
behavior
,
ExecutorService
backgroundExecutor
,
Executor
callbackExecutor
,
Call
<
T
>
delegate
)
{
if
(
callbackExecutor
==
null
)
{
callbackExecutor
=
new
Executor
()
{
@Override
public
void
execute
(
Runnable
command
)
{
command
.
run
();
}
};
}
BehaviorCall
(
NetworkBehavior
behavior
,
ExecutorService
backgroundExecutor
,
Call
<
T
>
delegate
)
{
this
.
behavior
=
behavior
;
this
.
backgroundExecutor
=
backgroundExecutor
;
this
.
callbackExecutor
=
callbackExecutor
;
this
.
delegate
=
delegate
;
}
@SuppressWarnings
(
"CloneDoesntCallSuperClone"
)
// We are a final type & this saves clearing state.
@Override
public
Call
<
T
>
clone
()
{
return
new
BehaviorCall
<>(
behavior
,
backgroundExecutor
,
callbackExecutor
,
delegate
.
clone
());
return
new
BehaviorCall
<>(
behavior
,
backgroundExecutor
,
delegate
.
clone
());
}
@Override
public
void
enqueue
(
final
Callback
<
T
>
callback
)
{
...
...
@@ -70,47 +59,31 @@ final class BehaviorCall<T> implements Call<T> {
try
{
Thread
.
sleep
(
sleepMs
);
}
catch
(
InterruptedException
e
)
{
callFailure
(
new
InterruptedIOException
(
"canceled"
));
call
back
.
on
Failure
(
new
InterruptedIOException
(
"canceled"
));
return
false
;
}
}
return
true
;
}
private
void
callResponse
(
final
Response
<
T
>
response
)
{
callbackExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
callback
.
onResponse
(
response
);
}
});
}
private
void
callFailure
(
final
Throwable
throwable
)
{
callbackExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
callback
.
onFailure
(
throwable
);
}
});
}
@Override
public
void
run
()
{
if
(
canceled
)
{
callFailure
(
new
InterruptedIOException
(
"canceled"
));
call
back
.
on
Failure
(
new
InterruptedIOException
(
"canceled"
));
}
else
if
(
behavior
.
calculateIsFailure
())
{
if
(
delaySleep
())
{
callFailure
(
behavior
.
failureException
());
call
back
.
on
Failure
(
behavior
.
failureException
());
}
}
else
{
delegate
.
enqueue
(
new
Callback
<
T
>()
{
@Override
public
void
onResponse
(
final
Response
<
T
>
response
)
{
if
(
delaySleep
())
{
callResponse
(
response
);
call
back
.
on
Response
(
response
);
}
}
@Override
public
void
onFailure
(
final
Throwable
t
)
{
if
(
delaySleep
())
{
callFailure
(
t
);
call
back
.
on
Failure
(
t
);
}
}
});
...
...
retrofit-mock/src/main/java/retrofit2/mock/BehaviorDelegate.java
0 → 100644
浏览文件 @
d1782df6
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
retrofit2.mock
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Proxy
;
import
java.lang.reflect.Type
;
import
retrofit2.Call
;
import
retrofit2.CallAdapter
;
import
retrofit2.Retrofit
;
/**
* Applies {@linkplain NetworkBehavior behavior} to responses and adapts them into the appropriate
* return type using the {@linkplain Retrofit#callAdapterFactories() call adapters} of
* {@link Retrofit}.
*
* @see MockRetrofit#create(Class)
*/
public
final
class
BehaviorDelegate
<
T
>
{
private
final
Retrofit
retrofit
;
private
final
NetworkBehavior
behavior
;
private
final
Class
<
T
>
service
;
BehaviorDelegate
(
Retrofit
retrofit
,
NetworkBehavior
behavior
,
Class
<
T
>
service
)
{
this
.
retrofit
=
retrofit
;
this
.
behavior
=
behavior
;
this
.
service
=
service
;
}
public
T
returningResponse
(
Object
response
)
{
return
returning
(
Calls
.
response
(
response
));
}
@SuppressWarnings
(
"unchecked"
)
// Single-interface proxy creation guarded by parameter safety.
public
T
returning
(
Call
<?>
call
)
{
final
Call
<?>
behaviorCall
=
new
BehaviorCall
<>(
behavior
,
retrofit
.
client
().
getDispatcher
().
getExecutorService
(),
call
);
return
(
T
)
Proxy
.
newProxyInstance
(
service
.
getClassLoader
(),
new
Class
[]
{
service
},
new
InvocationHandler
()
{
@Override
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
Type
returnType
=
method
.
getGenericReturnType
();
Annotation
[]
methodAnnotations
=
method
.
getAnnotations
();
CallAdapter
<?>
callAdapter
=
retrofit
.
callAdapter
(
returnType
,
methodAnnotations
);
return
callAdapter
.
adapt
(
behaviorCall
);
}
});
}
}
retrofit-mock/src/main/java/retrofit2/mock/CallBehaviorAdapter.java
已删除
100644 → 0
浏览文件 @
2ea316cd
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
retrofit2.mock
;
import
java.util.concurrent.Executor
;
import
java.util.concurrent.ExecutorService
;
import
retrofit2.Call
;
import
retrofit2.Retrofit
;
public
final
class
CallBehaviorAdapter
implements
NetworkBehavior
.
Adapter
<
Call
<?>>
{
private
final
Executor
callbackExecutor
;
private
final
ExecutorService
backgroundExecutor
;
/**
* Create an instance with a normal {@link Retrofit} instance and an executor service on which
* the simulated delays will be created. Instances of this class should be re-used so that the
* behavior of every mock service is consistent.
*/
public
CallBehaviorAdapter
(
Retrofit
retrofit
,
ExecutorService
backgroundExecutor
)
{
this
.
callbackExecutor
=
retrofit
.
callbackExecutor
();
this
.
backgroundExecutor
=
backgroundExecutor
;
}
@Override
public
Call
<?>
applyBehavior
(
NetworkBehavior
behavior
,
Call
<?>
value
)
{
return
new
BehaviorCall
<>(
behavior
,
backgroundExecutor
,
callbackExecutor
,
value
);
}
}
retrofit-mock/src/main/java/retrofit2/mock/MockRetrofit.java
浏览文件 @
d1782df6
...
...
@@ -15,34 +15,35 @@
*/
package
retrofit2.mock
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Proxy
;
import
retrofit2.Retrofit
;
public
final
class
MockRetrofit
{
public
static
MockRetrofit
create
(
Retrofit
retrofit
)
{
return
create
(
retrofit
,
NetworkBehavior
.
create
());
}
public
static
MockRetrofit
create
(
Retrofit
retrofit
,
NetworkBehavior
behavior
)
{
return
new
MockRetrofit
(
retrofit
,
behavior
);
}
private
final
Retrofit
retrofit
;
private
final
NetworkBehavior
behavior
;
private
final
NetworkBehavior
.
Adapter
<
Object
>
adapter
;
@SuppressWarnings
(
"unchecked"
)
//
public
MockRetrofit
(
NetworkBehavior
behavior
,
NetworkBehavior
.
Adapter
<?>
adapter
)
{
this
.
adapter
=
(
NetworkBehavior
.
Adapter
<
Object
>)
adapter
;
public
MockRetrofit
(
Retrofit
retrofit
,
NetworkBehavior
behavior
)
{
this
.
retrofit
=
retrofit
;
this
.
behavior
=
behavior
;
}
public
Retrofit
retrofit
()
{
return
retrofit
;
}
public
NetworkBehavior
networkBehavior
()
{
return
behavior
;
}
@SuppressWarnings
(
"unchecked"
)
// Single-interface proxy creation guarded by parameter safety.
public
<
T
>
T
create
(
Class
<
T
>
service
,
final
T
instance
)
{
return
(
T
)
Proxy
.
newProxyInstance
(
service
.
getClassLoader
(),
new
Class
[]
{
service
},
new
InvocationHandler
()
{
@Override
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
if
(
method
.
getDeclaringClass
()
==
Object
.
class
)
{
return
method
.
invoke
(
this
,
args
);
}
method
.
setAccessible
(
true
);
// Just In Case™
Object
value
=
method
.
invoke
(
instance
,
args
);
return
adapter
.
applyBehavior
(
behavior
,
value
);
}
});
public
<
T
>
BehaviorDelegate
<
T
>
create
(
Class
<
T
>
service
)
{
return
new
BehaviorDelegate
<>(
retrofit
,
behavior
,
service
);
}
}
retrofit-mock/src/test/java/retrofit2/mock/MockRetrofitTest.java
浏览文件 @
d1782df6
...
...
@@ -30,7 +30,6 @@ import retrofit2.Callback;
import
retrofit2.Response
;
import
retrofit2.Retrofit
;
import
static
java
.
util
.
concurrent
.
Executors
.
newSingleThreadExecutor
;
import
static
java
.
util
.
concurrent
.
TimeUnit
.
MILLISECONDS
;
import
static
java
.
util
.
concurrent
.
TimeUnit
.
SECONDS
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
...
...
@@ -52,20 +51,20 @@ public final class MockRetrofitTest {
.
baseUrl
(
"http://example.com"
)
.
build
();
DoWorkService
mockService
=
new
DoWorkService
()
{
MockRetrofit
mockRetrofit
=
MockRetrofit
.
create
(
retrofit
,
behavior
);
final
BehaviorDelegate
<
DoWorkService
>
delegate
=
mockRetrofit
.
create
(
DoWorkService
.
class
);
service
=
new
DoWorkService
()
{
@Override
public
Call
<
String
>
response
()
{
return
Calls
.
response
(
"Response!"
);
Call
<
String
>
response
=
Calls
.
response
(
"Response!"
);
return
delegate
.
returning
(
response
).
response
();
}
@Override
public
Call
<
String
>
failure
()
{
return
Calls
.
failure
(
mockFailure
);
Call
<
String
>
failure
=
Calls
.
failure
(
mockFailure
);
return
delegate
.
returning
(
failure
).
failure
();
}
};
NetworkBehavior
.
Adapter
<?>
adapter
=
new
CallBehaviorAdapter
(
retrofit
,
newSingleThreadExecutor
());
MockRetrofit
mockRetrofit
=
new
MockRetrofit
(
behavior
,
adapter
);
service
=
mockRetrofit
.
create
(
DoWorkService
.
class
,
mockService
);
}
@Test
public
void
syncFailureThrowsAfterDelay
()
{
...
...
samples/src/main/java/com/example/retrofit/SimpleMockService.java
浏览文件 @
d1782df6
...
...
@@ -3,19 +3,16 @@ package com.example.retrofit;
import
com.example.retrofit.SimpleService.Contributor
;
import
com.example.retrofit.SimpleService.GitHub
;
import
com.google.common.util.concurrent.ThreadFactoryBuilder
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.TimeUnit
;
import
retrofit2.Call
;
import
retrofit2.Retrofit
;
import
retrofit2.mock.CallBehaviorAdapter
;
import
retrofit2.mock.Calls
;
import
retrofit2.mock.BehaviorDelegate
;
import
retrofit2.mock.MockRetrofit
;
import
retrofit2.mock.NetworkBehavior
;
...
...
@@ -26,9 +23,11 @@ import retrofit2.mock.NetworkBehavior;
public
final
class
SimpleMockService
{
/** A mock implementation of the {@link GitHub} API interface. */
static
final
class
MockGitHub
implements
GitHub
{
private
final
BehaviorDelegate
<
GitHub
>
delegate
;
private
final
Map
<
String
,
Map
<
String
,
List
<
Contributor
>>>
ownerRepoContributors
;
public
MockGitHub
()
{
public
MockGitHub
(
BehaviorDelegate
<
GitHub
>
delegate
)
{
this
.
delegate
=
delegate
;
ownerRepoContributors
=
new
LinkedHashMap
<>();
// Seed some mock data.
...
...
@@ -48,7 +47,7 @@ public final class SimpleMockService {
response
=
contributors
;
}
}
return
Calls
.
response
(
response
);
return
delegate
.
returningResponse
(
response
).
contributors
(
owner
,
repo
);
}
public
void
addContributor
(
String
owner
,
String
repo
,
String
name
,
int
contributions
)
{
...
...
@@ -72,26 +71,24 @@ public final class SimpleMockService {
.
baseUrl
(
SimpleService
.
API_URL
)
.
build
();
// Create
the Behavior object which manages the fake behavior and the background executor
.
// Create
a MockRetrofit object with a NetworkBehavior which manages the fake behavior of calls
.
NetworkBehavior
behavior
=
NetworkBehavior
.
create
();
ExecutorService
bg
=
Executors
.
newSingleThreadExecutor
(
new
ThreadFactoryBuilder
()
.
setNameFormat
(
"mock-retrofit-%d"
)
.
setDaemon
(
true
)
.
build
());
MockRetrofit
mockRetrofit
=
MockRetrofit
.
create
(
retrofit
,
behavior
);
// Create the mock implementation and use MockRetrofit to apply the behavior to it.
MockRetrofit
mockRetrofit
=
new
MockRetrofit
(
behavior
,
new
CallBehaviorAdapter
(
retrofit
,
bg
));
MockGitHub
mockGitHub
=
new
MockGitHub
();
GitHub
gitHub
=
mockRetrofit
.
create
(
GitHub
.
class
,
mockGitHub
);
BehaviorDelegate
<
GitHub
>
delegate
=
mockRetrofit
.
create
(
GitHub
.
class
);
MockGitHub
gitHub
=
new
MockGitHub
(
delegate
);
// Query for some contributors for a few repositories.
printContributors
(
gitHub
,
"square"
,
"retrofit"
);
printContributors
(
gitHub
,
"square"
,
"picasso"
);
// Using the mock
object, add some additional mock
data.
// Using the mock
-only methods, add some additional
data.
System
.
out
.
println
(
"Adding more mock data...\n"
);
mockGitHub
.
addContributor
(
"square"
,
"retrofit"
,
"Foo Bar"
,
61
);
mockGitHub
.
addContributor
(
"square"
,
"picasso"
,
"Kit Kat"
,
53
);
gitHub
.
addContributor
(
"square"
,
"retrofit"
,
"Foo Bar"
,
61
);
gitHub
.
addContributor
(
"square"
,
"picasso"
,
"Kit Kat"
,
53
);
// Reduce the delay to make the next calls complete faster.
behavior
.
setDelay
(
500
,
TimeUnit
.
MILLISECONDS
);
// Query for the contributors again so we can see the mock data that was added.
printContributors
(
gitHub
,
"square"
,
"retrofit"
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录