koush / ion

Android Asynchronous Networking and Image Loading
Other
6.29k stars 1.04k forks source link

Can we mock out network calls for testing? #164

Open kaushikgopal opened 10 years ago

kaushikgopal commented 10 years ago

I'm searching for a simple way to mock out network calls made by Ion and return dummy json string.

1.Is this currently possible?

  1. It would be nice to have the same pleasant API that Ion uses elsewhere. Maybe something like:
Ion.with(context, "http://example.com/thing.json")
.mockCall()
.asJsonObject(testJsonObject);
koush commented 10 years ago

Hey, got your email. Sorry I didn't respond, got caught up with some other work. But I have been thinking about it quite a bit.

What you suggested was one of the ideas I had in mind.

The other idea is:

Ion.with(context, "mock://something.com/foo.json") .asJsonObject()

and then insert a custom uri handler for mock:// into Ion (already supported) that returns whatever mock data you want.

I think the prior is easier, since it super simple. But the latter doesn't introduce mock calls into the API. LMK your thoughts.

kaushikgopal commented 10 years ago

No issues at all. Wasn't sure if you got my mail so posted an issue here just in case.

ah interesting... never thought of approaching this with custom uri handlers. Here are my initial thoughts on both approaches:

Approach 2. mock uri handlers

I can definitely see the appeal in not polluting the API with additional mock calls.

Here's a sample example which concerns me though: I have a whole bunch of model entity objects like "user", "event", "photo" etc. and each of these have method calls "saveToServerAndDatabase". These save to my local database and then shoot out an Ion call with a url that's auto-formed depending on the model.

 user = http://api.myserver.com/u/id/create.json
 entity = http://api.myserver.com/e/id/create.json
 photo = http://api.myserver.com/p/id/create.json 

Now when i'm testing my app in a basic CRUD test flow, I use my entity objects and would like them to follow their usual flow with just the network calls mocked out (not sure if this is an unusual case).

If i had to do this with the mock uri handler, I would have to, in some way change the urls just when testing. Probably use a flag that tells me if i want my calls to get mocked instead of sending the regular uri call. A likely disadvantage of this, is that the logic creeps into my code (Or am i missing a simpler way of achieving this?).

Approach 1. mock API

The reason I like this approach is that I can control the behavior completely from my test code. The internal code is oblivious to the test settings and continues to function as normal. For this reason, this approach makes me feel the network call to the server as a blackbox sort of interaction.

I tell Ion to always return a mock object, whenever it intercepts a url call to "http://api.myserver.com/u/id/create.json" etc.

koush commented 10 years ago

Well, it doesn't have to be mock:// uris. You can intercept http:// uri calls as well if you want.

This may be the best of both worlds.

An idea would be to store a directory/file structure like the following in your test apk "assets" directory:

assets/
 - api.myserver.com/
   - u/
     - id/
       - create.json
     - e/
        - create.json
     - p/
        - create.json

Then inject a http request loader that returns data from your assets directory if it exists.

koush commented 10 years ago

LMK what you think about that. I can add something like that fairly easily. Would help with my own ion unit tests as well. Right now I actually start up a real webserver on localhost :p

kaushikgopal commented 10 years ago

Yup, that sounds like it would be perfect !

Just so i understand it correctly. We place the test data in the asset folder with the structure you mention, and then during testing we inject the http request loader (and it picks up the mock data if present).

Can you point me to some sample code where you inject the loader. I presume i would have to do this in my test setup/preparation phase?

I really like it!

koush commented 10 years ago

That's the idea. I'll set something up like that. Haven't done it yet, but it is fairly trivial.

koush commented 10 years ago

I've fixed up the getAssets stuff mentioned in the previous post. looking into this now. it's a bit more complicated than i had anticipated.

quentin23soleil commented 10 years ago

Where are we about this?

eugenkiss commented 9 years ago

Hi @koush,

I'm currently in need of the mocking functionality discussed in this issue here. See https://github.com/eugenkiss/chanobol/issues/34 for my use case, if you're interested.

Basically, I'd like to know if you could give me a pointer on what would be the best or easiest approach to implement a mocked Loader that intercepts certain HTTP Ion calls and returns an image from the assets folder. I've collected some ideas in https://github.com/eugenkiss/chanobol/issues/34 and your input would be very helpful. Thanks.

subodh-malgonde commented 9 years ago

Any updates on this?