I am developing an app using the MVP architecture. I am trying to test the Interactors of my app using MockWebServer. Well, I have this test:
@RunWith(RobolectricTestRunner::class)
@Config(constants = BuildConfig::class, manifest = "src/main/AndroidManifest.xml", packageName = "br.com.simplepass.simplepassnew", sdk = intArrayOf(23))
class LoginInteractorImplTest {
lateinit var mLoginInteractor : LoginInteractor
lateinit var mServer: MockWebServer
@Before
fun setUp(){
mLoginInteractor = LoginInteractorImpl()
mServer = MockWebServer()
mServer.start()
}
@Test
fun loginTest(){
mServer.url("http://192.168.0.10:8080/login")
val testSubscriber = TestSubscriber.create<User>()
mLoginInteractor.login("31991889992", "lala").subscribe(testSubscriber)
testSubscriber.assertNoErrors()
// testSubscriber.assertCompleted()
}
@After
fun tearDown(){
mServer.shutdown()
}
}
But, when I uncomment the assertCompleted on the TestSubscriber, I always get assertionError... I know the TestSubscriber works, because I use it in other tests.
Here is my ApiCall:
@GET("login")
fun login() : Observable<User>
My NetModule:
@Module
class NetModule(val mBaseUrl: String) {
@Provides
@Singleton
fun provideHttpCache(application: Application): Cache {
val cacheSize = 10 * 1024 * 1024
return Cache(application.cacheDir, cacheSize.toLong())
}
@Provides
@Singleton
fun provideOkhttpClient(cache: Cache) : OkHttpClient {
val client = OkHttpClient.Builder()
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
client.addInterceptor(interceptor)
return client.cache(cache).build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(mBaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(okHttpClient)
.build()
}
}
And my base URL (There's no backend server... could be anything):
<string name="api_base_url">http://192.168.0.12:8080</string>
So, What am I missing? This code should be working...
Any help is welcome!
EDIT:
So, I changed the code to this:
mLoginInteractor = LoginInteractorImpl()
mServer = MockWebServer()
mServer.enqueue(MockResponse()
.setResponseCode(200)
.setBody(Gson().toJson(User(1, "991889992", "Leandro", "123"))))
mServer.start()
val client = OkHttpClient.Builder()
val cacheSize = 10 * 1024 * 1024
client.cache(Cache(application.cacheDir, cacheSize.toLong())).build()
mLoginInteractor.setRetrofit(Retrofit.Builder()
.baseUrl(mServer.url("/"))
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(client.cache(Cache(application.cacheDir, cacheSize.toLong())).build())
.build())
And this:
val testSubscriber = TestSubscriber.create<User>()
mLoginInteractor.login("31991889992", "lala").subscribe(testSubscriber)
testSubscriber.assertNoErrors()
testSubscriber.assertReceivedOnNext(listOf(User(1, "991889992", "Leandro", "123")))
testSubscriber.assertCompleted()
But I still get this error:
Number of items does not match. Provided: 1 Actual: 0.
Provided values: [User(id=1, phoneNumber=991889992, name=Leandro, password=123)]
Actual values: []
There are a couple of things going on here. First, MockWebServer.url()
resolves the given url against the mock server's base url, it does not set the url. If you want to set the url, you'll need to pass it to the start()
method. Generally, you configure your retrofit to call the server's endpoint --
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(server.url("/"))
// Other builder methods.
.build();
Second, to get responses from the mock web server, you need to enqueue the expected responses as MockResponse
s. Otherwise it doesn't know what to send back. Do something like the following before making your request --
server.enqueue(new MockResponse().setBody("Success!"));
You'll need to build your response to mirror the expected response.
See the README for some more examples.