我对手机上的单元测试真的很陌生。我想为Android移动应用程序编写JUnit测试。我遇到了在IDE中测试的Robolectric(对我来说,Eclipse)
但我真的不明白Robolectric的Shadow对象。我应该用它们作为嘲笑吗? ShadowActivity等Shadow对象的使用目的是什么?
例如,我在几乎所有的Activity类中都使用了onCreate方法中的Crashlytics,Google Analytics代码。当Robolectric遇到这些线时会抛出错误。 ShadowActivity可以解决这些类型的问题吗?
我很抱歉,但正如我所说,我在单元测试中非常陌生,Robolectric文档对初学者没有帮助。
答案 0 :(得分:13)
但我真的不明白Robolectric的Shadow对象。我是不是该 用它们作为嘲弄?这些Shadow对象的用途是什么 像ShadowActivity等?
阴影有点像嘲笑或存根,但不完全相同。存在阴影以添加可在测试中用于检查底层Android对象的状态的其他方法。例如,许多Android对象具有某些值的设置器,但没有getter。我们可以在阴影中添加getter并在test中使用它们来断言底层对象。
例如,我在onCreate中使用了Crashlytics,Google Analytics代码 几乎每个Activity类中的方法。当Robolectric抛出错误时 它碰到了这些线条。 ShadowActivity能否解决这些问题 问题类型?
可能不是。为此,您应该使用依赖注入将错误版本的Crashlytics或GoogleAnalytics注入您的测试中。
Robolectric的目的是假装足够的Android平台允许你 在桌面JVM上运行测试 - 而不是模拟Android。仍然可以使用良好的工程实践,例如依赖注入或模拟。
我很抱歉,但正如我所说,我在单元测试方面真的很陌生 Robolectric文档对初学者没有帮助。
我同意。我们正努力让它变得更好,但我们还有很长的路要走。
答案 1 :(得分:0)
关于:
例如,我在onCreate中使用了Crashlytics,Google Analytics代码 几乎每个Activity类中的方法。当Robolectric抛出错误时 它碰到了这些线条。 ShadowActivity能否解决这些问题 问题类型?
您可以在Facade实现中包含对库的调用,该实现实现某种AnalyticsFacade并创建一个封装所有实现的类,并将公共行为委托给它们。
public interface Analytics{
void sendEvent(String category, String action, Map<String,String> params);
void log(String msg);
}
public class AnalyticsFacade implements Analytics{
private List<Analytics> analyticsServices;
public AnalyticsFacade()
{
this.analyticsServices = new ArrayList<Analytics>();
}
public void addAnalyticsService(Analytics analytics){
analyticsServices.add(analytics);
}
@Override
public void sendEvent(String category, String action, Map<String, String> params)
{
for(Analytics service: analyticsServices){
service.sendEvent(category,action,params);
}
}
@Override
public void log(String msg)
{
for(Analytics service: analyticsServices){
service.log(msg);
}
}
}
public class GoogleAnalytics implements Analytics{
private Tracker tracker;
public GoogleAnalytics(Tracker tracker)
{
this.tracker = tracker;
}
@Override
public void sendEvent(String category, String action, Map<String, String> params)
{
//Note that this method signature has changed since GA v2 , now you pass a Map and
//it has a builder in order to create it
tracker.send(category,action,params);
}
@Override
public void log(String msg)
{
throw new RuntimeException("Not implemented");
}
}