我想在标准的Android JUnit检测测试用例中使用RoboGuice,并使用模拟覆盖我应用程序的一部分实际接线进行测试。我在网上找不到任何解释如何执行此操作的内容,因为我的所有搜索结果都通过RoboGuoice转到Robolectric。我没有使用Robolectric,也不能出于各种原因在我的应用程序中使用它。是否有人使用RoboGuice连接应用并为标准 Android Intrumentation测试用例注入了模拟?
答案 0 :(得分:0)
我正在使用Roboguice 3,我使用标准setup
中的以下teardown
和ActivityInstrumentationTestCase2
方法解决了这个问题。
显然,您需要使用自己的测试模块类替换下面代码段中的new TestModule()
。
@Override
protected void setUp() throws Exception {
super.setUp();
Application app = (Application)getInstrumentation().getTargetContext()
.getApplicationContext();
RoboGuice.getOrCreateBaseApplicationInjector(app, RoboGuice.DEFAULT_STAGE,
Modules.override(RoboGuice.newDefaultRoboModule(app))
.with(new TestModule()));
getActivity();
}
@Override
protected void tearDown() throws Exception {
RoboGuice.Util.reset();
super.tearDown();
}
答案 1 :(得分:0)
我设法以简单的使用方式使其工作,您只需使用构建器绑定规则内的依赖关系,以后可能会忘记它们,它将自行完成所有操作。你可能认为它过度设计了,但如果tyou里面有很多带有robo guice依赖的测试类,那么重用它真的很好。 测试类中的用法如下:
@Rule
public InjectWithMocksRule injectWithMocksRule = new InjectWithMocksRule(
this,
() -> new InjectRule
.BindingBuilder()
.add(MyClass.class, mockedClassImpl)
.add(SomeInterface.class, mockedInterfaceImpl));
我写了帮助类TestBindingModule:
public class TestBindingModule extends AbstractModule {
private HashMap<Class<?>, Object> bindings = new HashMap<Class<?>, Object>();
@Override
@SuppressWarnings("unchecked")
protected void configure() {
Set<Entry<Class<?>, Object>> entries = bindings.entrySet();
for (Entry<Class<?>, Object> entry : entries) {
bind((Class<Object>) entry.getKey()).toInstance(entry.getValue());
}
}
public void addBinding(Class<?> type, Object object) {
bindings.put(type, object);
}
public void addBindings(HashMap<Class<?>, Object> bindings) {
this.bindings.putAll(bindings);
}
public static void setUp(Object testObject, TestBindingModule module) {
Module roboGuiceModule = RoboGuice.newDefaultRoboModule(RuntimeEnvironment.application);
Module testModule = Modules.override(roboGuiceModule).with(module);
RoboGuice.getOrCreateBaseApplicationInjector(RuntimeEnvironment.application, RoboGuice.DEFAULT_STAGE, testModule);
RoboInjector injector = RoboGuice.getInjector(RuntimeEnvironment.application);
injector.injectMembers(testObject);
}
public static void tearDown() {
Application app = RuntimeEnvironment.application;
DefaultRoboModule defaultModule = RoboGuice.newDefaultRoboModule(app);
RoboGuice.getOrCreateBaseApplicationInjector(app, RoboGuice.DEFAULT_STAGE, defaultModule);
}
}
比我使用自定义Rule
让它变得简单:
public class InjectRule implements TestRule {
public interface BindingBuilderFactory {
BindingBuilder create();
}
public static class BindingBuilder {
private HashMap<Class<?>, Object> bindings = new HashMap<>();
public BindingBuilder add(Class<?> dependencyClass, Object implementation) {
bindings.put(dependencyClass, implementation);
return this;
}
HashMap<Class<?>, Object> buildBindings() {
return this.bindings;
}
}
private Object target;
private BindingBuilderFactory bindingBuilderFactory;
public InjectRule(Object target, BindingBuilderFactory bindingBuilderFactory) {
this.target = target;
this.bindingBuilderFactory = bindingBuilderFactory;
}
private void overrideTestInjections(Object target) {
TestBindingModule module = new TestBindingModule();
module.addBindings(this.bindingBuilderFactory.create().buildBindings());
TestBindingModule.setUp(target, module);
}
@Override
public Statement apply(Statement base, Description description) {
return new StatementDecorator(base);
}
private class StatementDecorator extends Statement {
private Statement baseStatement;
StatementDecorator(Statement b) {
baseStatement = b;
}
@Override
public void evaluate() throws Throwable {
before();
try {
baseStatement.evaluate();
} catch (Error e) {
throw e;
} finally {
after();
}
}
void after() {
TestBindingModule.tearDown();
}
void before() {
overrideTestInjections(target);
}
}
}
此外,您可能希望在测试类中使用mocks
注释初始化@Mock
,因此您需要另一个自定义规则:
public class MockitoInitializerRule implements TestRule {
private Object target;
public MockitoInitializerRule(Object target) {
this.target = target;
}
@Override
public Statement apply(Statement base, Description description) {
return new MockitoInitializationStatement(base, target);
}
private class MockitoInitializationStatement extends Statement {
private final Statement base;
private Object test;
MockitoInitializationStatement(Statement base, Object test) {
this.base = base;
this.test = test;
}
@Override
public void evaluate() throws Throwable {
MockitoAnnotations.initMocks(test);
base.evaluate();
}
}
}
最后,你想首先将它们组合到模拟模拟中,然后将它们设置为依赖项:
public class InjectWithMocksRule implements TestRule {
private final RuleChain delegate;
public InjectWithMocksRule(Object target, InjectRule.BindingBuilderFactory bindingBuilderFactory) {
delegate = RuleChain
.outerRule(new MockitoInitializerRule(target))
.around(new InjectRule(target, bindingBuilderFactory));
}
@Override
public Statement apply(Statement base, Description description) {
return delegate.apply(base, description);
}
}