I'm learning Dagger and the biggest motivator behi...
# dagger
c
I'm learning Dagger and the biggest motivator behind learning it is to test deterministic responses from my backend. I'm following the typical Android arch guide, so yeah (I know I'm a bad person for using AAC VMs) Activity + Fragments + AAC VMs and a Repository. My "issue" is that it seems like I could just use Dagger to swap out Repository and FakeRepository and that would work... but it looks like I could also just use MockWebServer so I could mock the entire server interaction, as well as failures, etc etc. Does anyone have advice on to what route to go? My thinking that having a Repository and FakeRepository isn't actually all that helpful anymore and that MockWebServer from okhttp would actually be a ton better. In that case though... I don't think I would need Dagger at all? I'd love to be able to run my app in mock server mode though. Any advice would be appreciated. TLDR Which layer is the right one to fake stuff? VMs? Repository/FakeRepository? or real server and MockWebServer? Leaning MockWebServer
w
For instrumented tests I’d go with mocking server responses, so that you cover as much production code as you possibly can. Swapping on class level is useful for substituting implementations that reach out to things you can’t reasonably control in tests, like google sign in, perhaps location, connecting to bluetooth devices etc.
In that case though... I don’t think I would need Dagger at all?
Everything you can do with Dagger, you can also do without it. Dagger is supposed to be convenient, but the benefits are more pronounced in bigger apps. Generally to use MockWebServer, you need to be hitting its endpoint and not your production one, which means you need to pass a different base URL to your repository class (or wherever you make the requests). With Dagger it’s convenient to provide web server URL and change it for tests. If you can substitute the URL in tests without Dagger then you can start with that
Overall replacing implementations in UI tests is both under- and overrated IMO. On one hand it’s very powerful and useful with actual things you can’t control in UI tests. For example we substitute implementation of push messaging for one where we can send pushes from tests, we substitute google sign in for one that doesn’t require test device to be logged in. We inject test analytics implementation to be able to assert events. Networking is mocked with MockWebServer, and we use Dagger to substitute base URL. But to be able to use Dagger for such substitutions, you need to be careful about separating implementations that you want to swap from other logic — for example we still run code that parses the push json in UI tests, despite being easily able to do that in the firebase service. But then swapping for test pushes implementation would reduce useful coverage
c
Interesting. It makes sense. So I guess I will start at the MockWebServer layer first because I feel like this would catch a lot of issues in my moshi adapters and stuff like that. Another example that happens often (and this might be a separate question) is that I have 90+ network calls and I all want them running against my dev server environment, but the new api call that my team is working on is not yet ready but we have the json. Do you have any opinions on that @wasyl and whether or not dagger would necessarily help me there? I'm assuming it wouldn't, but again I'm new to dagger so I'm just trying to find any "tricks" to these kinds of common problems.
w
Does this new API implement exactly the same functionality as the old one?
c
No. It's a brand new endpoint for some new functionality we're building (in this example that I'm giving). So a lot of times we agree with the backend on the response, and I'm trying to find an easy way where we can go in and say "Hey add this .json file and this single retrofit call will actually try to use this json file instead of trying to get it over the network"
w
Ah, so you want to use the real server for old API calls, but not for the new ones? I think this is similarly not necessarily matter of whether you’re using Dagger, but how you’ve structured your code. If you have two networking clients, you can pass different base URLs for both, and you can do that with or without Dagger, really
👍 1
t
fwiw in instrumentation tests I usually recommend using a fake/mock api service interface since your json parser configuration can be tested on the jvm in a unit test config, and the rest is likely going to be code mostly inside libraries like retrofit/okhttp, which are well tested already and not what your tests need to worry about.
g
+1 to mock server approach, coverage would be much better. You of course don't need instrumentation tests for adapter itself, and unit test is of course make sense, as Trevor pointed out, but idea of using real network layer for instrumentation tests to handle all together, with configured adapters, interceptors, auth, logging, DI etc. One more advantage is that you emulate API behavior,not just provide result of parsing of this response Tho we use mock api service approach too, but moving to mock web server approach instead
c
Thanks @gildor I'm also assuming that there's no "dagger" magic that has to happen in the case of mock web server, it's just providing a different url?
g
What is "dagger magic"? In case of mock web server we provide different base url which used for creation of API services, we just pass mock web server url
c
Got it. I think I misworded my above question by saying dagger magic, but if it's just a URL, then it makes sense that I could just use dagger to give me the proper URL. Thanks