Android 测试:使用 Dagger2 + Gradle
Android Tests: use Dagger2 + Gradle
我了解 Dagger2 的工作原理,
我知道它允许轻松交换依赖关系,因此我们可以使用模拟进行测试。
重点是我不确定我是否理解我应该如何为测试和 debug/production.
提供不同的 Dagger2 组件实现
我是否需要创建 2 个 Gradle productFlavors(例如 "Production"/"Test")
将包含 2 个不同的组件定义?
或者我可以指定我想使用模拟组件进行测试编译,使用非模拟组件进行非测试构建吗?
我很困惑,请澄清一下就好了!
非常感谢!
单元测试
Don’t use Dagger for unit testing
为了测试带有 @Inject
注释构造函数的 class,您不需要匕首。而是使用具有虚假或模拟依赖项的构造函数创建一个实例。
final class ThingDoer {
private final ThingGetter getter;
private final ThingPutter putter;
@Inject ThingDoer(ThingGetter getter, ThingPutter putter) {
this.getter = getter;
this.putter = putter;
}
String doTheThing(int howManyTimes) { /* … */ }
}
public class ThingDoerTest {
@Test
public void testDoTheThing() {
ThingDoer doer = new ThingDoer(fakeGetter, fakePutter);
assertEquals("done", doer.doTheThing(5));
}
}
Functional/integration/end-to-end 测试
Functional/integration/end-to-end tests typically use the production
application, but substitute fakes[^fakes-not-mocks] for persistence,
backends, and auth systems, leaving the rest of the application to
operate normally. That approach lends itself to having one (or maybe a
small finite number) of test configurations, where the test
configuration replaces some of the bindings in the prod configuration.
这里有两个选择:
选项 1:通过子classing 模块覆盖绑定
@Component(modules = {AuthModule.class, /* … */})
interface MyApplicationComponent { /* … */ }
@Module
class AuthModule {
@Provides AuthManager authManager(AuthManagerImpl impl) {
return impl;
}
}
class FakeAuthModule extends AuthModule {
@Override
AuthManager authManager(AuthManagerImpl impl) {
return new FakeAuthManager();
}
}
MyApplicationComponent testingComponent = DaggerMyApplicationComponent.builder()
.authModule(new FakeAuthModule())
.build();
选项 2:单独的组件配置
@Component(modules = {
OAuthModule.class, // real auth
FooServiceModule.class, // real backend
OtherApplicationModule.class,
/* … */ })
interface ProductionComponent {
Server server();
}
@Component(modules = {
FakeAuthModule.class, // fake auth
FakeFooServiceModule.class, // fake backend
OtherApplicationModule.class,
/* … */})
interface TestComponent extends ProductionComponent {
FakeAuthManager fakeAuthManager();
FakeFooService fakeFooService();
}
中了解更多信息
我了解 Dagger2 的工作原理,
我知道它允许轻松交换依赖关系,因此我们可以使用模拟进行测试。
重点是我不确定我是否理解我应该如何为测试和 debug/production.
提供不同的 Dagger2 组件实现我是否需要创建 2 个 Gradle productFlavors(例如 "Production"/"Test") 将包含 2 个不同的组件定义?
或者我可以指定我想使用模拟组件进行测试编译,使用非模拟组件进行非测试构建吗?
我很困惑,请澄清一下就好了!
非常感谢!
单元测试
Don’t use Dagger for unit testing
为了测试带有 @Inject
注释构造函数的 class,您不需要匕首。而是使用具有虚假或模拟依赖项的构造函数创建一个实例。
final class ThingDoer {
private final ThingGetter getter;
private final ThingPutter putter;
@Inject ThingDoer(ThingGetter getter, ThingPutter putter) {
this.getter = getter;
this.putter = putter;
}
String doTheThing(int howManyTimes) { /* … */ }
}
public class ThingDoerTest {
@Test
public void testDoTheThing() {
ThingDoer doer = new ThingDoer(fakeGetter, fakePutter);
assertEquals("done", doer.doTheThing(5));
}
}
Functional/integration/end-to-end 测试
Functional/integration/end-to-end tests typically use the production application, but substitute fakes[^fakes-not-mocks] for persistence, backends, and auth systems, leaving the rest of the application to operate normally. That approach lends itself to having one (or maybe a small finite number) of test configurations, where the test configuration replaces some of the bindings in the prod configuration.
这里有两个选择:
选项 1:通过子classing 模块覆盖绑定
@Component(modules = {AuthModule.class, /* … */})
interface MyApplicationComponent { /* … */ }
@Module
class AuthModule {
@Provides AuthManager authManager(AuthManagerImpl impl) {
return impl;
}
}
class FakeAuthModule extends AuthModule {
@Override
AuthManager authManager(AuthManagerImpl impl) {
return new FakeAuthManager();
}
}
MyApplicationComponent testingComponent = DaggerMyApplicationComponent.builder()
.authModule(new FakeAuthModule())
.build();
选项 2:单独的组件配置
@Component(modules = {
OAuthModule.class, // real auth
FooServiceModule.class, // real backend
OtherApplicationModule.class,
/* … */ })
interface ProductionComponent {
Server server();
}
@Component(modules = {
FakeAuthModule.class, // fake auth
FakeFooServiceModule.class, // fake backend
OtherApplicationModule.class,
/* … */})
interface TestComponent extends ProductionComponent {
FakeAuthManager fakeAuthManager();
FakeFooService fakeFooService();
}
中了解更多信息