Robolectric的暗影对象和嘲弄

时间:2013-11-15 09:36:21

标签: java android unit-testing junit robolectric

我对手机上的单元测试真的很陌生。我想为Android移动应用程序编写JUnit测试。我遇到了在IDE中测试的Robolectric(对我来说,Eclipse)

但我真的不明白Robolectric的Shadow对象。我应该用它们作为嘲笑吗? ShadowActivity等Shadow对象的使用目的是什么?

例如,我在几乎所有的Activity类中都使用了onCreate方法中的Crashlytics,Google Analytics代码。当Robolectric遇到这些线时会抛出错误。 ShadowActivity可以解决这些类型的问题吗?

我很抱歉,但正如我所说,我在单元测试中非常陌生,Robolectric文档对初学者没有帮助。

2 个答案:

答案 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");
    }
}