android-test-demo icon indicating copy to clipboard operation
android-test-demo copied to clipboard

The activity should be set a component for testing, not the app

Open stephanenicolas opened this issue 9 years ago • 5 comments

It's too central the current way. In the activity, it scales up.

stephanenicolas avatar Nov 05 '15 06:11 stephanenicolas

Not sure what's the problem? Also how do you set the component in the activity before it starts its lifecycle i.e. onCreate?

chiuki avatar Nov 05 '15 17:11 chiuki

You got full control over it in your tests. Robolectric can build it and give it back to you before you call onCreate, same for the ActivityTestRule in Espresso.

The problem is that the app having the component of each activity would make it ugly, if that is done at the activity level, then code is prettier and the solution scales easily, without classes left out (open closed principle).

S.

2015-11-05 9:23 GMT-08:00 Chiu-Ki Chan [email protected]:

Not sure what's the problem? Also how do you set the component in the activity before it starts its lifecycle i.e. onCreate?

— Reply to this email directly or view it on GitHub https://github.com/chiuki/android-test-demo/issues/11#issuecomment-154128610 .

stephanenicolas avatar Nov 05 '15 20:11 stephanenicolas

@stephanenicolas But this is an application scoped component, hence it should be the application the one that holds its reference.

mdelolmo avatar Oct 02 '16 22:10 mdelolmo

Hi Stephane. I was lending a hand with this issue. I'm having trouble understanding what you mean. Are you saying that we should create the component in the activity? I'm having trouble figuring out what the issue is. Thanks and have a nice day

digitalbuddha avatar Nov 15 '16 02:11 digitalbuddha

Hi Mike,

it's been such a while I wrote that comment ;)

But yeah, what I meant is that:

((DemoApplication) getApplication()).component().inject(this);

uses the app as a repository to get the component used for injection. It would be better to have the component used by the activity at the activity level. My comment was really about : if you have 20 activities, you are gonna create quite a lot of pollution in the app class to provide the components for all activities. I understand that @mdelolmo says it's an app component, but here it's not so clear I would say as the component is used unchanged by the activity. So it looks quite a lot like an activity component !

====start of parenthesis Actually, and that is a bit different, when I re-read the example I also find it a bit awkward that the application knows about the activity: it knows about it transitively via the DemoComponent interface. I understand that this example is a toy but it gives the feeling of quite an un-layered wiring: things at the app level know about things at the activity level.

Let's think of it in term of the class loader: loading the app loads the app component then loads all sub components interfaces then loads all classes of all activities... This is not exactly ideal.

The approach you have in: http://fr.slideshare.net/nakhimovich/advanced-dagger-talk-from-360andev slide 47 also has the same issue I would say: the plusing of the activity component in the app component also leads to this transgression of layers. Would it be possible to do it the other way around and have the activity component use the application component ? === end of parenthesis

I am not exactly sure about a better way to do things with dagger 2, but as Uncle Bob says all design problems have a single solution: introduce a new indirection layer ;) (I quite probably take shortcuts in his thoughts actually). Of course, this means that you want to use Dagger 2 during tests, which doesn't seem so recommended by the authors. By this I mean having a test for the activity that uses DI.

Here it would be interesting to have a new entity responsible for providing the component to the activity and you can replace this entity by a stub that will return a stub component during tests. Something like the component factory you use in your slides (48). Either a method of the activity returns this entity and you can test of subclass of your activity (bouhh) or you have a setter that you call in your tests when your activity has just been created to provide a fake component factory. This can be done at the instrumentation level during testing and be plugged in each test itself as you do it in your slides (67-69, 77-78).

It's 4-5 AM, not so sure I am clear and accurate on this ;)

Note: I find myself very good not even to have mentioned toothpick even once, I could as it doesn't have this kind of issues ... ;)

stephanenicolas avatar Nov 15 '16 02:11 stephanenicolas