google / dagger

A fast dependency injector for Android and Java.
https://dagger.dev
Apache License 2.0
17.45k stars 2.02k forks source link

Testing/Overriding Modules #110

Closed chrisjenx closed 8 years ago

chrisjenx commented 9 years ago

Apologies if this is a dup (couldn't see an open issue).

Is there any standard way to do testing. Overriding @Provides or extending module classes.
I know it was discussed by Jake at Devvox that it still needs fleshing out.

What are the current thoughts? This for me is the only real blocker. I can work around the limitations, but it feels like yak-shaving.

stephanenicolas commented 8 years ago

Send the link mike please

Le dim. 13 déc. 2015 19:58, Mike Nakhimovich notifications@github.com a écrit :

Not sure if this doesn't fit someone's use case but here's a gist showing a really simple way to override dependencies in dagger2

— Reply to this email directly or view it on GitHub https://github.com/google/dagger/issues/110#issuecomment-164316500.

pyricau commented 8 years ago

What @netdpb suggests works great. Here's what it looks like.

In prod:

@Component(modules={AppModule.class, ProdModule.class})
public interface AppGraph {
  void inject(MyApp app);
}

@Module(modules={ /** List all the modules that are shared here **/ }
public class AppModule{}

@Module(/** List modules containing only bindings that should be redefined **/)
public class ProdModule {}

public class MyApp extends Application {

  public void onCreate() {
    super.onCreate();
    AppGraph graph = createAppGraph();
    graph.inject(this);
  }

  protected AppGraph createAppGraph() {
    return DaggerAppGraph.builder().build();
  }
}

In test:

@Component(modules={AppModule.class, TestModule.class})
public interface TestAppGraph extends AppGraph {
}

@Module(/** List modules containing redefined  bindings **/)
public class TestModule {}

public class MyTestApp extends MyApp {
  @Override protected AppGraph createAppGraph() {
    return DaggerTestAppGraph.builder().build();
  }
}
dalewking commented 8 years ago

Basically, the workaround is that if in Dagger 1 you had Module B extend Module A, in Dagger 2 you add a Module C and move anything that isn't overridden by module B from module A to module C.

I know this works and is what we had to do to our app, but Dagger 2 really should support the overrides like in Dagger 1, it is much more convenient.

PaulWoitaschek commented 8 years ago

@pyricau How do you set the created MyTestApp when you need it in an ActivityInstrumentationTestCase2 for example?

artem-zinnatullin commented 8 years ago

@PaulWoitaschek you can do it via custom instrumentation test runner, see http://artemzin.com/blog/how-to-mock-dependencies-in-unit-integration-and-functional-tests-dagger-robolectric-instrumentation/ for more details

tobeylin commented 8 years ago

Does anyone use DaggerMock? Maybe this can make overriding a module easier. https://github.com/fabioCollini/DaggerMock

yairkukielka commented 8 years ago

What @pyricau says sound great. I have the same question as @PaulWoitaschek. I know it's been answered by @artem-zinnatullin, but using a custom instrumentation test runner will use that MyTestApp for all instrumented tests (I want to use different TestModule's in different tests)

Is there a way to use @pyricau 's solution only for some of the instrumented tests in Android? I'm specifically thinking of a way of creating a JUnit Rule to achieve this behavior (or similar) per test.

tbroyer commented 8 years ago

FWIW, there's now some "official" documentation up at https://google.github.io/dagger/testing.html

apiltamang commented 8 years ago

As @tbroyer said, the official documentation lists some good points. The concept outlined are more generic than for android-specific use cases. For someone like me, i.e. leveraging dagger 2 on a non-android application, the official testing documentation was a lot more readable.

NitroG42 commented 8 years ago

The documentation makes it a lot better but I still can't figure out how to do that when we have component dependencies/subcomponent. Basically, if I have an AppComponent (containing the context, for example), and a NetworkComponent that requires a context (that is provided by a module of AppComponent). I want to replace the NetworkComponent by a MockNetworkComponent. I tried both solution (component dependencies/subcomponent), and none worked :

Does someone have a solution ? I'm not far from trying Dagger 1 at this point.

ScottPierce commented 8 years ago

@NitroG42 Difficulty with testing is one of the reasons Square (the company that made Dagger 1) still hasn't changed to Dagger 2.

JakeWharton commented 8 years ago

We have quite a bit of Dagger 2, actually.

On Wed, Apr 20, 2016 at 10:18 PM Scott Pierce notifications@github.com wrote:

@NitroG42 https://github.com/NitroG42 Difficulty with testing is one of the reasons Square (the company that made Dagger 1) still hasn't changed to Dagger 2.

— You are receiving this because you are subscribed to this thread.

Reply to this email directly or view it on GitHub https://github.com/google/dagger/issues/110#issuecomment-212696425

ScottPierce commented 8 years ago

My mistake. I had assumed differently a few months ago from this thread: https://github.com/JakeWharton/u2020/issues/158

ronshapiro commented 8 years ago

I'm closing this issue since we've published our testing patterns in the link that @tbroyer added above. If you have further questions, definitely feel free to reach out.

dalewking commented 8 years ago

So why did you close #213 at the same time? Nothing has been resolved regarding #213 to my knowledge. The testing patterns link might be useful to someone doing a desktop or server app, but does not help one iota with Android, which is what I was addressing in #213

ronshapiro commented 8 years ago

We have seen several Android apps using those patterns.

mheras commented 8 years ago

I still think there is no easy and clean way to do it in Android...

pyricau commented 8 years ago

There's probably some work to be done with more samples to explain how to have different configurations in test, dev & release on Android. Overall though, everything works just fine, and it's all documented in some way in this issue.

caltseng commented 5 years ago

@mattkranzler5 - I'm trying to follow your pattern in my code, but I'm running into duplicate class errors in compilation. Is this something you've encountered?

dexmagic commented 5 years ago

@caltseng has a point - the dependency management issues that come up with Dagger is a real problem. Worst case scenario is some future build tanks because the dependency tree gets wack. Which I've seen a lot of.

Anyway, scoping members to default and using class factors is a great way to get around dagger limitations. I'd give that a try and then see if the library is worth the effort.

Other issues you can run into relate to lifecycle. People often end up calling init in the Application class to get around the fact that you have to clean things up properly when onStop/pause/saveinstancestate/destroy are called.

Let's just say your mileage will vary on that.