2013-11-15 76 views
5

我真的很陌生,在移动设备上进行单元测试。我想为Android移动应用程序编写JUnit测试。我碰到Robolectric这是测试IDE(对我来说,Eclipse)Robolectric的阴影对象和嘲讽

但我真的不明白Robolectric的阴影对象。我应该用它们作为嘲弄吗? ShadowActivity等Shadow对象的用途是什么?

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

对不起,但正如我所说我真的是新单元测试和Robolectric文档对初学者没有帮助。

回答

12

但是我真的不明白Robolectric的暗影物体。我应该 使用它们作为嘲弄吗? ShadowActivity等Shadow objects 的使用目的是什么?

阴影有点像嘲笑或存根,但不完全相同。存在阴影以添加可用于测试的其他方法,以检查底层Android对象的状态。例如,许多Android对象具有特定值的setter,但没有getter。我们可以将getter添加到阴影中,并在测试中使用它们来对基础对象进行断言。

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

可能不是。为此,您应该使用依赖注入将Crashlytics或GoogleAnalytics的假版本注入您的测试。

Robolectric的目的是为了虚拟出足够的Android平台,让您在桌面JVM上运行测试 - 而不是模拟Android。良好的工程实践,如依赖注入或模拟仍然可以使用。

对不起,但正如我所说我真的是新单元测试和 Robolectric文档对初学者没有帮助。

我同意。我们试图让它变得更好,但我们还有很长的路要走。

0

关于:

例如,我有Crashlytics,在的onCreate 方法谷歌分析代码,几乎在每一个Activity类。当它遇到这些线时,Robolectric会抛出错误。 ShadowActivity可以解决这些类型的问题吗?

您可以将库的调用包装在实现某种AnalyticsFacade的Facade实现中,并创建一个封装所有实现的类并将公共行为委托给它们。

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