andrzejchm / restmock Goto Github PK
View Code? Open in Web Editor NEWHTTP Server for Android Instrumentation tests
Home Page: https://medium.com/@andrzejchm/ittd-instrumentation-ttd-for-android-4894cbb82d37#.uir3loxu7
License: Apache License 2.0
HTTP Server for Android Instrumentation tests
Home Page: https://medium.com/@andrzejchm/ittd-instrumentation-ttd-for-android-4894cbb82d37#.uir3loxu7
License: Apache License 2.0
java.lang.NullPointerException: Attempt to invoke virtual method 'void io.appflate.restmock.MatchableCallsRequestDispatcher.removeAllMatchableCalls()' on a null object reference
at io.appflate.restmock.RESTMockServer.reset(RESTMockServer.java:130)
at com.example.e2etests.tests.AbstractTest.tearDown(AbstractTest.java:61)
We just started getting this crash on some our tests. It's happening in our test @After
tear down method. Looking at the RESTMock source I guess this is possible if RestMock is not initialized. But we are initializing RESTMock when our test application starts
AndroidAssetsFileParser restMockFileParser = new AndroidAssetsFileParser(InstrumentationRegistry.getContext());
RESTMockServerStarter.startSync(restMockFileParser, new AndroidLogger());
And of course this was working just fine until this week. We are on version 0.3.2
Hi 👋
Would you be open to accepting a PR for enabling Android X support - or is it something that is already road mapped?
Hi,
I have added the dependency as
dependencies {
androidTestCompile 'com.github.andrzejchm.RESTMock:android:0.2.1'
}
also included the maven url in the project build.gradle.
But I am not able to access the api.
When I keep the below as dependency
dependencies {
compile 'com.github.andrzejchm.RESTMock:android:0.2.1'
}
then I am able to access the API.
Could you please let me know which one to follow
Thanks,
Chaitanya
Hi, I'm using RESTMock and I'm loving it. But I was trying to mock GET request with path matchers but I always got MOCK ERRORS. When I'm doing a simple request to http://test-server.org/get/true
and I add a matcher pathEndsWith("true")
I get a NOT MOCKED ERROR. The exact same request but without the pathEndsWith("true")
works. See example below with logs.
whenGET(pathEndsWith("true")).thenReturnFile(RESTMOCK_GET_PATH_URL)
D/RESTMock: ## Adding new response for: (HTTP method is: GET and url ends with: true)
D/OkHttp: --> GET http://test-server.org/get/true http/1.1
D/OkHttp: --> END GET
D/RESTMock: -> New Request: GET / HTTP/1.1
E/RESTMock: <- Response ERROR: NOT MOCKED: GET / HTTP/1.1
D/OkHttp: <-- 500 Server Error http://localhost:36316/ (4ms)
D/OkHttp: Content-Length: 10
D/OkHttp: NOT MOCKED
D/OkHttp: <-- END HTTP (10-byte body)
I/MockWebServer: MockWebServer[36316] received request: GET / HTTP/1.1 and responded: HTTP/1.1 500 Server Error
whenRequested(isGET()).thenReturnFile(RESTMOCK_GET_PATH_URL)
D/RESTMock: ## Adding new response for: HTTP method is: GET
D/OkHttp: --> GET http://test-server.org/get/true http/1.1
D/OkHttp: --> END GET
D/RESTMock: -> New Request: GET / HTTP/1.1
D/RESTMock: <- Response: HTTP/1.1 200 OK
I/MockWebServer: MockWebServer[40123] received request: GET / HTTP/1.1 and responded: HTTP/1.1 200 OK
D/OkHttp: <-- 200 OK http://localhost:40123/ (5ms)
D/OkHttp: Content-Length: 27
D/OkHttp: { "getIsSuccessful": true}
D/OkHttp: <-- END HTTP (27-byte body)
Hi,
It would be great if RESTMock could inform us about the reason of the failure.
At this moment, when something goes wrong, it provides pretty generic information about the error:
INFO: MockWebServer[50062] received request: GET /channel/list HTTP/1.1 and responded: HTTP/1.1 500 Server Error
It's pretty hard to figure out what's wrong in such case - sometimes it's missing file, sometimes it's an other problem. More info would be really helpful.
Best regards
Hi,
First of all thank you for this awesome library!
We are trying to intercept the request to check POST's body parameters to return a response depending on a body parameter value. We are trying to do that with the method thenAnswer
that needs as a parameter a io.appflate.restmock.MockAnswer
but this interface is not public so we cannot access to it.
This is intentional? If it is, how can we achieve our goal to return a response depending on a body parameter?
If it's not, please could you make it public?
Thanks!
RESTMock uses OkHttp v. 3.4.0:
https://github.com/andrzejchm/RESTMock/blob/develop/core/build.gradle#L49
However, as per the release notes, this has a security hole that should be avoided:
https://github.com/square/okhttp/blob/master/CHANGELOG.md#version-341
As such, we should update from 3.4.0 to 3.4.1.
Hi,
First of all thanks for the great library. I've used RESTMock in the past around 2yrs back and everything worked smoothly. I was trying it today and faced some issues.
I have a simple test method
@Test
fun shouldShowLoader() {
RESTMockServer.whenGET(RequestMatchers.pathContains("abc.json"))
.thenReturnFile(200, "abc/abc.json")
activityRule.launchActivity(null)
onView(withId(R.id.errorContainer)).check(matches(isDisplayed()))
}
I'm getting this exception in logs :
URL its hitting: https://localhost:40882/abc.json?key=abc&q=mock
I/MockWebServer: MockWebServer[40882] connection from /127.0.0.1 failed: javax.net.ssl.SSLHandshakeException: Handshake failed D/OkHttp: <-- HTTP FAILED: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Tried a lot of solutions but nothing worked out. I'm using Android P for testing.
The app is working fine without any issue in production. Its just the UI tests I'm struggling with.
I'm looking for a method like server.takeRequest()
which allows me to verify the body of the request, is there anyway?
Does RESTMock provide regex support for URL matching?
Why I get the below error.
E/RESTMock: <- Response ERROR: NOT MOCKED: GET /ServiceStatus HTTP/1.1
Below is my code
@rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(HomePageActivity.class,false,true);
@Before
public void init() {
//be sure to reset it before each test!
RESTMockServer.reset();
}
@Test
public void shouldDisplayUpgradeRequiredMessage() {
RESTMockServer.whenGET(pathContains("ServiceStatus"))
.thenReturnFile(200, "ServiceStatus.json");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
RequestsVerifier.verifyGET(pathEndsWith("ServiceStatus.json")).exactly(1);
onView(ViewMatchers.withId(R.id.tvServiceMessage)).check(matches(withText(UpgradeMessage)));
}
This is the detailed stacktrace
04-25 19:55:28.008 17309-17309/CommCore.avv.Debug D/LifecycleMonitor: Lifecycle status change: CommCore.avv.app.homepage.HomePageActivity@c0dfeb5 in: STARTED
04-25 19:55:28.009 17309-17340/CommCore.avv.Debug D/OkHttp: --> GET http://localhost:44683/ServiceStatus http/1.1
04-25 19:55:28.009 17309-17340/CommCore.avv.Debug D/OkHttp: Referer: http://localhost:44683/?OS=Android&OSVersion=7.1.1&Make=unknown&Model=Android SDK built for x86&AppVersion=4.05.0&ScreenWidth=1080&ScreenHeight=1776&UUID=641c8afde8f574b1
04-25 19:55:28.009 17309-17340/CommCore.avv.Debug D/OkHttp: --> END GET
04-25 19:55:28.010 17309-17309/CommCore.avv.Debug D/LifecycleMonitor: Lifecycle status change: CommCore.avv.app.homepage.HomePageActivity@c0dfeb5 in: RESUMED
04-25 19:55:28.022 17309-17341/CommCore.avv.Debug D/RESTMock: -> New Request: GET /ServiceStatus HTTP/1.1
04-25 19:55:28.022 17309-17341/CommCore.avv.Debug E/RESTMock: <- Response ERROR: NOT MOCKED: GET /ServiceStatus HTTP/1.1
04-25 19:55:28.023 17309-17341/CommCore.avv.Debug I/MockWebServer: MockWebServer[44683] received request: GET /ServiceStatus HTTP/1.1 and responded: HTTP/1.1 500 Server Error
04-25 19:55:28.024 17309-17340/CommCore.avv.Debug D/OkHttp: <-- 500 Server Error http://localhost:44683/ServiceStatus (15ms)
Hello,
I love this library and have been using it for a long time. Is there any chance the artifacts can be hosted somewhere more stable than jitpack? It's been down for most of the day and our CI builds get stuck when it's down. Thanks!
I have a PUT request that slowly streams bytes to a server. Internal to this call I track total bytes uploaded. I now want to write a test asserting that X bytes were uploaded. To do this I mostly need to keep RESTMock from immediately returning 200. It should let me write some bytes and only later return a response code. IIUC from other issues, .delay()
operator only delays the response body, not the response code. Is there any way to change this?
Kotlin version: 1.1.0
RESTMock Version: 0.2.1
Hi
I'm trying to use your library in Kotlin with JUnit robolectric tests and getting following exception:
Exception in thread "pool-3-thread-1" java.lang.VerifyError: Cannot inherit from final class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at org.robolectric.internal.bytecode.SandboxClassLoader.maybeInstrumentClass(SandboxClassLoader.java:138)
at org.robolectric.internal.bytecode.SandboxClassLoader.findClass(SandboxClassLoader.java:101)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at io.appflate.restmock.RESTMockServer.init(RESTMockServer.java:54)
at io.appflate.restmock.RESTMockServerStarter$1.run(RESTMockServerStarter.java:44)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
This exception seems to be thrown within RESTMockServer.init() method, when new MockWebServer object is trying to be created.
It's also kinda weird because everything works well in instrumented android tests.
I created a sample kotlin project with your library here where this problem exists, so I would be very grateful if you could take a look on this in your spare time.
As you will see, I included there all stuff from your robolectric sample.
Have you ever met similar problem while working on your library?
When I convert MainActivityTest.java
to kotlin, it gives below error:
$ adb shell am instrument -w -r -e notPackage org.bouncycastle.pqc.crypto.qtesla -e debug false -e class 'io.appflate.restmock.androidsample.tests.MainActivityTest' io.appflate.restmock.androidsample.test/io.appflate.restmock.androidsample.CustomTestRunner
Connected to process 8637 on device 'lge-nexus_5x-024c6d7f5e96d337'.
Started running tests
java.lang.ClassNotFoundException: io.appflate.restmock.androidsample.tests.MainActivityTest
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:400)
at androidx.test.internal.runner.TestLoader.doCreateRunner(TestLoader.java:72)
at androidx.test.internal.runner.TestLoader.getRunnersFor(TestLoader.java:104)
at androidx.test.internal.runner.TestRequestBuilder.build(TestRequestBuilder.java:793)
at androidx.test.runner.AndroidJUnitRunner.buildRequest(AndroidJUnitRunner.java:547)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:390)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1932)
Caused by: java.lang.ClassNotFoundException: Didn't find class "io.appflate.restmock.androidsample.tests.MainActivityTest" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/data/app/io.appflate.restmock.androidsample.test-1/base.apk", zip file "/data/app/io.appflate.restmock.androidsample-2/base.apk"],nativeLibraryDirectories=[/data/app/io.appflate.restmock.androidsample.test-1/lib/arm64, /data/app/io.appflate.restmock.androidsample-2/lib/arm64, /system/lib64, /vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
... 8 more
Tests ran to completion.
Hello,
I've got an issue using the gradle Plugin. With the last update I'm not able to open relative paths in my project. The issue appeared by upgrading com.android.tools.build:gradle
from 3.4.2 to 3.5.0.
thenReturnFile
is not able to open asset files and crashes when using mockserver in connected tests with the following error:
E/RESTMock: <- Response FILE READ ERROR
java.io.FileNotFoundException
We could have brought it to work by using the following code:
context.getAssets()
.open(**FILEPATH**)
.use { Log.d("test", it.bufferedReader().readLine()) }
After upgrading from RESTMock 0.1.1 to RESTMock 0.1.3, I'm beginning to see the following exceptions in tests that use RESTMock:
java.lang.IncompatibleClassChangeError: Implementing class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at org.robolectric.internal.bytecode.InstrumentingClassLoader.findClass(InstrumentingClassLoader.java:153)
at org.robolectric.internal.bytecode.InstrumentingClassLoader.loadClass(InstrumentingClassLoader.java:95)
at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:109)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:157)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170)
at okhttp3.RealCall.execute(RealCall.java:60)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171)
at rx.Subscriber.setProducer(Subscriber.java:209)
at rx.Subscriber.setProducer(Subscriber.java:205)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
at rx.Observable.subscribe(Observable.java:8553)
at rx.Observable.subscribe(Observable.java:8520)
at com.thisclicks.core.api.AvatarServiceApiTest.itShouldReturnUserDoesNotHaveAValidAvatar(AvatarServiceApiTest.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:105)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:56)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:64)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
I suspect this is caused by one or more of the libraries we're using being a different version than that of RESTMock's libraries. Specifically, I suspect one of the OkHttp libraries, but I'm not sure how to track down exactly which one. For our project, we use the following library definition:
compile "com.android.support:appcompat-v7:23.2.1"
compile 'com.google.code.gson:gson:2.3.0'
compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.trello:rxlifecycle:0.4.0'
compile 'com.trello:rxlifecycle-components:0.4.0'
apt 'com.google.dagger:dagger-compiler:2.0.1'
compile 'com.google.dagger:dagger:2.0.1'
compile "com.squareup.retrofit2:retrofit:2.0.2"
compile "com.squareup.retrofit2:adapter-rxjava:2.0.2"
compile "com.squareup.retrofit2:converter-gson:2.0.2"
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
compile "au.com.gridstone.rxstore:rxstore:5.0.2"
compile "au.com.gridstone.rxstore:converter-gson:5.0.2"
compile "com.android.support:design:23.2.1"
compile "com.google.android.gms:play-services-base:8.4.0"
compile "com.google.android.gms:play-services-plus:8.4.0"
compile "com.google.android.gms:play-services-location:8.4.0"
compile "com.google.android.gms:play-services-auth:8.4.0"
compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') {
transitive = true;
}
compile "joda-time:joda-time:2.8.2"
testCompile 'junit:junit:4.12'
testCompile 'com.squareup.assertj:assertj-android:1.1.0'
testCompile 'org.robolectric:robolectric:3.0'
testCompile 'org.mockito:mockito-core:1.9.5'
testCompile 'org.powermock:powermock-module-junit4:1.6.5'
testCompile 'org.powermock:powermock-api-mockito:1.6.5'
testCompile 'com.github.andrzejchm.RESTMock:android:0.1.3'
deployerJars 'org.apache.maven.wagon:wagon-ssh:2.2'
deployerJars 'org.apache.maven.wagon:wagon-ssh-external:2.2'
This is blocking me from testing two other patches to RESTMock that I had previously planned on posting.
I have gone through and looked at the dependency changes from 0.1.1 -> 0.1.3, and changed the dependencies that overlap to match the RESTMock versions, but without success. I'm wondering if there is something else I could do to try and debug this problem so we can upgrade our library to RESTMock v0.1.3.
[To delete]
Hi,
the REST-Mock crashes when proguard obfuscation is applied and HTTPS is enabled.
Here is the stacktrace:
2020-05-08 14:19:07.799 13382-13475/xxx E/AndroidRuntime: FATAL EXCEPTION: pool-10-thread-1
Process: xxx, PID: 13382
java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String java.security.PublicKey.getAlgorithm()' on a null object reference
at java.security.KeyStore$PrivateKeyEntry.(KeyStore.java:576)
at java.security.KeyStore$PrivateKeyEntry.(KeyStore.java:526)
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:485)
at java.security.KeyStore.getEntry(KeyStore.java:1560)
at com.android.org.conscrypt.KeyManagerImpl.(KeyManagerImpl.java:72)
at com.android.org.conscrypt.KeyManagerFactoryImpl.engineGetKeyManagers(KeyManagerFactoryImpl.java:115)
at javax.net.ssl.KeyManagerFactory.getKeyManagers(KeyManagerFactory.java:305)
According to this article the reason may be, that a deprecated version of spongycastle code to generate a self signed certificate is used:
http://quabr.com:8182/59848764/how-to-fix-proguard-removes-java-security-code
Regards
Benjamin
Hi Andrew,
Thanks for great library!
I am facing either a bug or misuse situation, here is the scenario:
RESTMockServer.whenGET(pathContains(".../" + valueLongId)) .thenReturnString(responseJson)
For the above scenario, I would expect mocking to work because from test perspective both specified requests and responses are identical? Lib version 0.2.1.
MockWebServer allows us to assert that certain web requests were made:
// Optional: confirm that your app made the HTTP requests you were expecting.
RecordedRequest request1 = server.takeRequest();
assertEquals("/v1/chat/messages/", request1.getPath());
assertNotNull(request1.getHeader("Authorization"));
RecordedRequest request2 = server.takeRequest();
assertEquals("/v1/chat/messages/2", request2.getPath());
RecordedRequest request3 = server.takeRequest();
assertEquals("/v1/chat/messages/3", request3.getPath());
This functionality isn't wrapped by RESTMock. It would be great if we could used this half of MockWebServer.
At the very least, RESTMock should expose the mock server so we can manually assert; TL;DR RESTMockServer.mockWebServer
should be public or exposed by getter
I'm going to fix a potential NPE in the code base. I thought it would be helpful to annotate the potentially-null-variable as @Nullable
. I see you don't do this anywhere yet. Do you have any plans to do this? Did you explicitly not do this?
Hi, when I try to include androidTestCompile 'com.github.andrzejchm.RESTMock:android:0.1.2', I get the following error:
Error:Module 'com.github.andrzejchm.RESTMock:android:0.1.2' depends on one or more Android Libraries but is a jar
But version 0.1.1 works fine with no issues.
Thoughts?
We have set up RESTMockServer using https by calling the following function in the Runner for our Android instrumented tests:
private fun provisionMockServer() {
RESTMockServer.enableLogging(LaundrappRESTMockLogger())
val builder = RESTMockOptions.Builder().useHttps(true).build()
RESTMockServerStarter.startSync(AndroidAssetsFileParser(context), AndroidLogger(), builder)
}
We also then pass the SSLSocketFactory into our production app as shown in the example app. Using this method works well with Android versions up to Android Oreo (API 27) but running tests fails with the following exception on an emulator running API 28:
E/AndroidRuntime: FATAL EXCEPTION: pool-4-thread-1
Process: com.company.ourapp, PID: 6114
java.lang.AssertionError: java.security.NoSuchAlgorithmException: The BC provider no longer provides an implementation for KeyPairGenerator.RSA. Please see https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html for more details.
at okhttp3.tls.HeldCertificate$Builder.generateKeyPair(HeldCertificate.java:429)
at okhttp3.tls.HeldCertificate$Builder.build(HeldCertificate.java:353)
at io.appflate.restmock.SslUtils.localhost(SslUtils.java:44)
at io.appflate.restmock.RESTMockServer.setUpHttps(RESTMockServer.java:91)
at io.appflate.restmock.RESTMockServer.init(RESTMockServer.java:74)
at io.appflate.restmock.RESTMockServerStarter$1.run(RESTMockServerStarter.java:56)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.security.NoSuchAlgorithmException: The BC provider no longer provides an implementation for KeyPairGenerator.RSA. Please see https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html for more details.
at sun.security.jca.Providers.checkBouncyCastleDeprecation(Providers.java:563)
at sun.security.jca.Providers.checkBouncyCastleDeprecation(Providers.java:330)
at java.security.KeyPairGenerator.getInstance(KeyPairGenerator.java:303)
at okhttp3.tls.HeldCertificate$Builder.generateKeyPair(HeldCertificate.java:425)
at okhttp3.tls.HeldCertificate$Builder.build(HeldCertificate.java:353)
at io.appflate.restmock.SslUtils.localhost(SslUtils.java:44)
at io.appflate.restmock.RESTMockServer.setUpHttps(RESTMockServer.java:91)
at io.appflate.restmock.RESTMockServer.init(RESTMockServer.java:74)
at io.appflate.restmock.RESTMockServerStarter$1.run(RESTMockServerStarter.java:56)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Running the production app works fine so this has to be an issue with our testing setup - most likely RESTMockServer's usage of OkHttp looking at the stacktrace.
useHttps should not be false by default?
I've upgraded my app to OkHttp 4.5.0 and I am no longer able to run RestMock tests. The app crashes with this error:
java.lang.NoSuchMethodError: No static method start$default(Lokhttp3/internal/http2/Http2Connection;ZILjava/lang/Object;)V in class Lokhttp3/internal/http2/Http2Connection; or its super classes (declaration of 'okhttp3.internal.http2.Http2Connection at okhttp3.internal.concurrent.TaskRunner.runTask(TaskRunner.kt:116) at okhttp3.internal.concurrent.TaskRunner.access$runTask(TaskRunner.kt:42) at okhttp3.internal.concurrent.TaskRunner$runnable$1.run(TaskRunner.kt:65) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:764)
Hi, first of all I really admire the simplicity.
but somehow I find it difficult to implement in my project.
so my project consist of multiple libraries in which consist of multiple api call from each Library.
I've followed all the guide given but still unable to mock the rest data (the RESTMock doesn't intercept the API call)
defaultConfig {
testInstrumentationRunner 'io.appflate.restmock.android.RESTMockTestRunner'
}
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
androidTestCompile ('com.github.andrzejchm.RESTMock:android:0.2.2') {
exclude module: 'okhttp'
}
exclude because of some conflict of versioning.
In my test:
public class SomeTest {
@Rule
public ActivityTestRule<LauncherActivity> mActivityTestRule = new
ActivityTestRule<>(LauncherActivity.class);
@Before
public void startUp() {
RESTMockServer.reset();
retrofit = new Retrofit.Builder()
.baseUrl(RESTMockServer.getUrl())
.build();
}
@Test
public void someTest() {
RESTMockServer.whenPOST(RequestMatchers.pathContains("customer/password_reset"))
.thenReturnEmpty(200);
// do something here and there
}
@After
public void tearDown() throws Exception {
HelperTool.clearApplicationData(context);
}
}
Above are some part of the code, I'm using espresso as you can notice in my gradle. when I run the code, the logcat still showing me that it points to my backend server. instead of RESTMockServer.getUrl()
Is there anything I missed here? Sorry still new in this
Attempting to use this library with SDK 28 results in:
java.lang.AssertionError: java.security.NoSuchAlgorithmException: The BC provider no longer provides an implementation for KeyPairGenerator.RSA. Please see https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html for more details.
at okhttp3.tls.HeldCertificate$Builder.generateKeyPair(HeldCertificate.java:429)
at okhttp3.tls.HeldCertificate$Builder.build(HeldCertificate.java:353)
at io.appflate.restmock.SslUtils.localhost(SslUtils.java:44)
at io.appflate.restmock.RESTMockServer.setUpHttps(RESTMockServer.java:91)
at io.appflate.restmock.RESTMockServer.init(RESTMockServer.java:74)
I'm assuming that switching over to a different keyAlgorithm will work. Thoughts?
Hi Below is the error i keep getting when using Rest Mock Server in my project.
I have followed the sample and still cant make it work.
i don't have this issue when i copy my json or test to the android Sample.
Below are some screenshots of my project state to see if i can be assisted.
I am using v0.4.0 of the Library to test this
I've upgraded my app to OkHttp 4.0.0 and I am no longer able to run RestMock tests. The app crashes with this error:
java.lang.NoSuchMethodError: No static method initializeInstanceForTests()V in class Lokhttp3/internal/Internal; or its super classes (declaration of 'okhttp3.internal.Internal' appears in /data/app/???-Erfx_-ETp-Rrby47elr7mg==/base.apk!classes34.dex)
at okhttp3.mockwebserver.MockWebServer.<clinit>(MockWebServer.java:105)
at io.appflate.restmock.RESTMockServer.init(RESTMockServer.java:70)
at io.appflate.restmock.RESTMockServerStarter$1.run(RESTMockServerStarter.java:56)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
The Mocked Server that is set up by RESTMock is using HTTP. Android SDK 28 will start to deny any connection between servers that are not using HTTPs. So, all the applications tests that are using SDK 28 will fail. Because they can not find the Mocked Response, the instrumented tests are going to crash.
Hi! We've been using restmock for a while now, and we're often getting this Exception in many of our builds while running Android UI tests.
We suspect it's happening when we reset the matched requests before a new test, and at the same time there are is request from the previous test still running, because Android shares the process between tests.
More specifically, this happens when we invoke RestMockServer.reset()
after a test, and at the same time the method getMatchedRequests()
is iterating the matchableCalls
list because some background thread made a request after the test already ended.
We try to avoid this by using IdlingResources to make Espresso wait for our background tasks, but having almost 300 tests the probability of leaking some request is quite high.
I can think of an easy solution by replacing the matchableCalls
type from LinkedList
to CopyOnWriteArrayList
.
This might cause the leaked request to not find a matched call and return an http 500 error , but that should be OK since the original test already finished, and I believe that's the currently expected behaviour. It's not a silver bullet solution to flaky tests, but it should help us quite a lot.
What do you think? Is it OK if I open a Pull Request? Or do you think there may be a better approach?
Here's the full stacktrace and some logs of the crash:
D/RESTMock(10912): -> New Request: GET /api/1/dictionary/professional-level HTTP/1.1
D/RESTMock(10912): ## Removing all responses
I/MockWebServer(10912): MockWebServer[39702] done accepting connections: Socket closed
I/MicrophoneInputStream( 2161): mic_close gzi@1f273041
I/HotwordRecognitionRnr( 2161): Hotword detection finished
I/HotwordRecognitionRnr( 2161): Stopping hotword detection.
I/System.out(10912): path: /api/1/dictionary/professional-level
--------- beginning of crash
E/AndroidRuntime(10912): FATAL EXCEPTION: OkHttp Http2Connection
E/AndroidRuntime(10912): Process: net.infojobs.mobile.android.debug, PID: 10912
E/AndroidRuntime(10912): java.util.ConcurrentModificationException
E/AndroidRuntime(10912): at java.util.LinkedList$LinkIterator.next(LinkedList.java:124)
E/AndroidRuntime(10912): at io.appflate.restmock.MatchableCallsRequestDispatcher.getMatchedRequests(MatchableCallsRequestDispatcher.java:96)
E/AndroidRuntime(10912): at io.appflate.restmock.MatchableCallsRequestDispatcher.dispatch(MatchableCallsRequestDispatcher.java:41)
E/AndroidRuntime(10912): at okhttp3.mockwebserver.MockWebServer$Http2SocketHandler.onStream(MockWebServer.java:942)
E/AndroidRuntime(10912): at okhttp3.internal.http2.Http2Connection$ReaderRunnable$1.execute(Http2Connection.java:673)
E/AndroidRuntime(10912): at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
E/AndroidRuntime(10912): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/AndroidRuntime(10912): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/AndroidRuntime(10912): at java.lang.Thread.run(Thread.java:818)
W/ActivityManager( 1489): Error in app net.infojobs.mobile.android.debug running instrumentation ComponentInfo{net.infojobs.mobile.android.debug.test/com.infojobs.app.testutil.InfojobsTestRunner}:
W/ActivityManager( 1489): java.util.ConcurrentModificationException
W/ActivityManager( 1489): java.util.ConcurrentModificationException
D/AndroidRuntime(10900): Shutting down VM
Hi,
Im working on iOS UItest and is RESTMockserver support for iOS.
Hi! would be really nice if we were able to do something like this:
whenGET(pathEndsWith("pokemon/1/"))
.thenReturnFile(200, "getPokemonDetails_200.json")
.delay(3, TimeUnit.SECONDS); // this!
Are there any plans to include something similar?
Thanks! Great work!
Hi!
We've been using WireMock for a while now on our app, and we're happy with it. But it's sometimes too heavy for Android development, and this library seems like an awesome lightweight replacement for it. Congratulations!
There's just one feature missing that stops us from adopting it, and it's having multiple matchings for a given request. For example having a very specific matching and a default fallback:
/api/login -> login_error_response.json
/api/login?user=me&pass=123 -> login_success_response.json
In this case the first matching would also match the second request, and RESTMock will return a MORE_THAN_ONE_RESPONSE_ERROR.
In WireMock the user can specify a priority value, and it will pick the highest one (the lower number means more priority).
In my example, I would set a priority 2 for the default error, and priority 1 for the success case.
Another approach would be to just pick the last one added. Both solutions are not mutually exclusive, although I think the one with priorities is more robust.
What do you think about having this feature? I think it could be implemented as a withPriority(int)
method on MatchableCall
.
Hello, I've got a little issue with the delay method :
The code
Here is the code, in a jUnit test:
RESTMockServer.whenRequested(pathContains(BernardAPI.LOGOUT))
.thenReturnString(200, "test response")
.delay(TimeUnit.SECONDS, 30);
RESTMockServer.enableLogging(new RESTMockLogger() {
@Override
public void log(String message) {
String m = message;
}
@Override
public void error(String errorMessage) {
String m = errorMessage;
}
@Override
public void error(String errorMessage, Throwable exception) {
String m = errorMessage;
}
});
Boolean result = bernardWebService.logout();
I run it on debug mode and I have breakpoints in each of the RESTMockLogger methods.
Expected behavior
When I run bernardWebService.logout(), it triggers a HTTP Request on a logout URL, catched by RESTMockServer. As I defined a delay of 30 seconds, I expect the Mock webserver to wait 30 seconds before sending a response (and I hope to get a timeout to test this case).
Actual behavior
When bernardWebService.logout() is triggered, I get into RESTMockLogger.log with this message:
-> New Request: GET /api/logout HTTP/1.1
About a second later, I'm back in my RESTMockLogger.log method with this message:
<- Response: HTTP/1.1 200 OK
As you can see, no delay is applied.
I tried with days and milliseconds unit. I tried to call the delay method before and after calling thenReturnString, it still doesn't work.
The sample app is using RESTMockServer.getSSLSocketFactory() and RESTMockServer.getTrustManager() in Retrofit OkHttp and is not working with it, returning the following error:
12-18 18:59:12.629 2471-3623/? E/NetdConnector: RCV <- {600 Iface linkstate wlan0 up} 12-18 18:59:32.638 2471-3623/? E/NetdConnector: RCV <- {600 Iface linkstate wlan0 up} 12-18 18:59:38.517 18827-18896/br.com.ioasys.fdc E/AndroidRuntime: FATAL EXCEPTION: OkHttp Http2Connection Process: br.com.ioasys.fdc, PID: 18827 java.lang.NoSuchMethodError: No virtual method getRequestHeaders()Ljava/util/List; in class Lokhttp3/internal/http2/Http2Stream; or its super classes (declaration of 'okhttp3.internal.http2.Http2Stream' appears in /data/app/br.com.ioasys.fdc-2/base.apk:classes3.dex) at okhttp3.mockwebserver.MockWebServer$Http2SocketHandler.readRequest(MockWebServer.java:937) at okhttp3.mockwebserver.MockWebServer$Http2SocketHandler.onStream(MockWebServer.java:910) at okhttp3.internal.http2.Http2Connection$ReaderRunnable$1.execute(Http2Connection.java:674) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818) 12-18 18:59:38.625 2471-3672/? E/ActivityManager: Will notifyMovedToHome from moveHomeStack 12-18 18:59:38.625 2471-3672/? E/ActivityManager: Broadcasting Moved to Home screen Intent 12-18 18:59:52.654 2471-3623/? E/NetdConnector: RCV <- {600 Iface linkstate wlan0 up} 12-18 19:00:12.375 2471-3627/? E/native: do suspend false
If I remove these methods related to SSL, it throws me an error related to SSL.
Retrofit version: 2.5.0
OkHttp version: 3.12.0
I have a test setup something like:
@RunWith(AndroidJUnit4.class)
public class SomeTest {
@Before
public void setUp() {
AndroidAssetsFileParser restMockFileParser
= new AndroidAssetsFileParser(InstrumentationRegistry.getContext());
RESTMockServerStarter.startSync(restMockFileParser);
...
I'm getting the following error when running any test
java.lang.NoSuchMethodError: No static method initializeInstanceForTests()V in class Lokhttp3/internal/Internal; or its super classes (declaration of 'okhttp3.internal.Internal' appears in /data/app/com.example.debug-1/base.apk)
I already have my proguard keeping everything in my test apk:
-dontnote **
-dontobfuscate
# hacky way to tell proguard to keep EVERYTHING
-keep class !non.existant.package.** { *; }
-dontwarn !non.existant.package.**,**
I can see the initializeInstanceForTests
method in the test apk:
However the method has been stripped from my app apk. This is expected since it isn't used in the app.
I can solve my problem by telling proguard to keep Internal
in my app apk:
-keepclassmembers public class okhttp3.internal.Internal{
*;
}
But why does this work?
I can follow the stack trace but everything looks like it shoiuld be happening in the test apk.
RESTMockServerStarter.startSync(restMockFileParser);
// produces the callstack:
// RESTMockServer.init(mocksFileParser, logger);
// ...
// RESTMockServer.mockWebServer = new MockWebServer();
// ...
// Internal.initializeInstanceForTests();
Why/how is RestMock
setting up MockWebServer
in my app apk not in my test apk?
Add a proxying feature which allows unmatched requests to be forwarded to the actual server. This would allow us to use RESTMock for developing new REST services without the implementation of the REST endpoint on the actual server.
See WireMock for more information: http://wiremock.org/docs/proxying/
I was wondering if you have the best practice for replacing an already mapped endpoint.
I have endpoints mapped as such (just an example):
val getSettings: MatchableCall
get() = whenRequested(allOf(
isGET(),
pathStartsWith("/api/v2/"),
pathEndsWithIgnoringQueryParams("settings.json")
))
I then have an initDefaultMocks function that maps endpoints with default responses. See below:
fun initDefaultMocks() {
postOauthMobile.thenReturnEmpty(200)
getSettings.thenReturnEmpty(200)
getUser.thenReturnEmpty(200)
}
What that means is that sometimes I need to remove the mock and add a different one (unique cases with their own mocks).
What is the best way to replace that endpoint mock? Ideally I'd like to be able to provide an endpoint matcher and remove/replace the response for that 🤔
Hiya,
Awesome library!
However.
We are in a situation where we want to test if a pull to refresh succeeds successfully.
See pseudo code
fun onPullToRefreshTheDataShouldBeDifferent() {
whenGET(pathEndsWith("/some/path")
.thenReturnFile("/file_with_json_1.json")
.thenReturnFile("/file_with_json_2.json"
launchActivity()
doAssertionViewHolder()
swipeToRefresh()
doAssertionDifferentViewHolderShouldNowBeVisible()
}
The RESTMockWebServer
seems to always return the first defined JSON
("/file_with_json_1.json").
Does this work like intended?
Because I don't see any samples like this on your repo
Thanks In advance.
Tim
When I write code like "RESTMockServer.whenGET(RequestMatchers.pathContains("users")).thenReturnFile(200, "json/users.json)",
the json file path is "E:\Android Projects\Leetcode\app\build\intermediates\sourceFolderJavaResources\test\debug\json\users.json", the test result is "java.io.FileNotFoundException: E:\Android%20Projects\Leetcode\app\build\intermediates\sourceFolderJavaResources\test\debug\json\users.json ". Is that any bug with the source code?
RestAdapter adapter = new RestAdapter.Builder()
.baseUrl(RESTMockServer.getUrl())
.build();
You mentioned that we need to change base url in native code by using TestApplicatiion. Why you need to this. The interceptor needs to works irespective to URL. sometime application has multiple URL and some developer dont want to change the code. It will be helpful that you provide the explaination. I read the tutorial mentioned in above step. I need to integrate this library for Espresso Tests
There have been a few features that have gone into the current development trunk. At my work, we're using jwir3/RESTMock instead of RESTMock's official distribution, because the features haven't been included yet.
This is just a friendly reminder to prepare a distribution. @andrzejchm if you don't have time and would like some assistance, I'd be happy to help maintain the package for you if you give me access.
Is it possible to intercept the request ? I'd like to adjust the response based on the parameters sent in the request (both in body and the url)
For example - When I send a request to the server with a specific ID (json body), I need the response from the server to contain the same ID.
With wiremock I used https://github.com/opentable/wiremock-body-transformer
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.