我正在为使用Reactive编程和Retrofit的类编写单元测试用例。我得到以下例外:
com.locationlabs.finder.android.core.manager.AuthManagerTest > logout_ok STANDARD_ERROR
Jan 07, 2016 11:28:06 PM com.squareup.okhttp.mockwebserver.MockWebServer$3 execute
INFO: MockWebServer[51867] starting to accept connections
Jan 07, 2016 11:28:07 PM com.squareup.okhttp.mockwebserver.MockWebServer$3 execute
WARNING: MockWebServer[51867] failed unexpectedly
java.lang.NoClassDefFoundError: com/squareup/okhttp/internal/framed/IncomingStreamHandler
at com.squareup.okhttp.mockwebserver.MockWebServer.serveConnection(MockWebServer.java:414)
at com.squareup.okhttp.mockwebserver.MockWebServer.access$800(MockWebServer.java:93)
at com.squareup.okhttp.mockwebserver.MockWebServer$3.acceptConnections(MockWebServer.java:389)
at com.squareup.okhttp.mockwebserver.MockWebServer$3.execute(MockWebServer.java:356)
at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.squareup.okhttp.internal.framed.IncomingStreamHandler
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 8 more
这是我的Retrofit类和Manager类。
import java.util.Map;
import retrofit.http.Body;
import retrofit.http.Headers;
import retrofit.http.POST;
import rx.Observable;
public interface AuthService {
@POST("auth/endAuthSession")
@Headers({"Content-Type: application/json"})
Observable<Void> logout();
}
public class AuthManager {
private AuthService authService;
public AuthManager(AuthService authService) {
this.authService = authService;
}
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import rx.Observable;
import rx.functions.Func1;
public Observable<Void> logout() {
return authService.logout()
.map(new Func1<Void, Void>() {
@Override
public Void call(Void nothing) {
JsonUtil.token = null;
return null;
}
});
}
}
以下是我的单元测试用例:
import com.ll.core.manager.AuthManager;
import com.ll.core.service.AuthService;
import retrofit.GsonConverterFactory;
import rx.Subscriber;
import rx.observers.TestSubscriber;
import junit.framework.Assert;
import com.google.gson.Gson;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.OkHttpClient;
import org.junit.Before;
import org.junit.Test;
import retrofit.JacksonConverterFactory;
import retrofit.Retrofit;
import retrofit.RxJavaCallAdapterFactory;
import java.io.IOException;
import java.lang.Override;
import java.lang.Throwable;
import java.lang.Void;
import java.net.HttpURLConnection;
/**
* Unit test case for AuthManager.
*/
public class AuthManagerTest {
private AuthService authService;
private MockWebServer server;
private Gson gson;
@Before
public void setup() throws IOException {
server = new MockWebServer();
server.start();
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(server.url("/"))
.addConverterFactory(JacksonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(new OkHttpClient())
.build();
authService = retrofit.create(AuthService.class);
}
@Test
public void logout_ok(){
//Setup resonse.
MockResponse response = new MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK);
server.enqueue(response);
AuthManager authManager = new AuthManager(authService);
TestSubscriber sub = new TestSubscriber();
authManager.logout().subscribe(sub);
sub.assertCompleted();
}
}
最初谷歌搜索表明应该包括okio
库。即使在包含`okio,库之后,我仍然遇到同样的异常。这是我的gradle文件。
dependencies {
compile group: 'com.google.android.gms', name: 'play-services-analytics', version: '8.4.0'
// HTTP libs
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.okhttp:okhttp:2.7.1'
compile 'com.squareup.okhttp:logging-interceptor:2.6.0'
// Reactive libs
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
// JSON libs
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.0-rc2'
compile 'com.fasterxml.jackson.core:jackson-core:2.7.0-rc2'
compile 'com.squareup.retrofit:converter-jackson:2.0.0-beta2'
// DI libs
compile group: 'com.google.dagger', name: 'dagger', version: '2.0.2'
apt group: 'com.google.dagger', name: 'dagger-compiler', version: '2.0.2'
provided 'org.glassfish:javax.annotation:10.0-b28'
// DB lib
compile 'io.realm:realm-android:0.87.1'
// Unit testing dependencies
testCompile 'junit:junit:4.12'
testCompile 'com.squareup.okio:okio:1.6.0'
testCompile 'com.squareup.okhttp:mockwebserver:2.5.0'
testCompile 'com.squareup.retrofit:retrofit-mock:2.0.0-beta2'
testCompile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
}
EDIT1 :
当我运行以下命令时:
jar -tvf ~/.gradle/caches/modules-2/files-2.1/com.squareup.okhttp/okhttp/2.5.0/4de2b4ed3445c37ec1720a7d214712e845a24636/okhttp-2.5.0.jar
我确实在jar中看到了这个类。
995 Tue Aug 25 21:12:54 PDT 2015 com/squareup/okhttp/internal/framed/IncomingStreamHandler$1.class
593 Tue Aug 25 21:12:54 PDT 2015 com/squareup/okhttp/internal/framed/IncomingStreamHandler.class
我仍然困惑为什么单元测试无法找到这个类,即使它在jar文件中。它看起来像Jar地狱问题。
EDIT2 :
这确实是Jar地狱的问题。
如果您注意到上面的gradle文件,我使用的是okhttp
的2.7.1版本,但mockwebser
使用的是2.5.0版本。当我使用2.7.1
版本的mockwebserver时,问题得到解决。
答案 0 :(得分:0)
在使用proguard混淆代码时,需要添加异常以避免来自proguard的类,方法或字段。您的大多数图书馆都处于危险区域的反射原因。您需要为每个使用例如RXJava,Dagger,Retrofit和GSON的库找到特定的proguard配置。
另一个解决方案是忘记预备或安全,就像避免整个改装包一样。