我有一个创建位图对象的类。
它需要访问位图资源,因此需要访问我传递给构造函数的上下文,所以我称之为 myClass(context)
理想情况下,我想以某种方式注入依赖。我想用工厂做这个,所以我可以向工厂询问对象并为我创建它,但我只能从创建新窗口的活动类中获取上下文。因此,我似乎必须继续从主要活动中传递上下文。
我最近问了一个类似的问题,并被告知我根本不应该静态调用上下文,并且应该总是传递它。
这意味着如果我想测试这个类,我的测试类需要访问android框架(这意味着我无法在本地测试并且必须使用AndroidTests)。
它是如何工作的?我的类只需要一个位图,但由于上下文,我现在无法在本地测试。
答案 0 :(得分:1)
如果您的班级只需要位图,为什么不能模拟位图?你应该测试你班上的逻辑。您不需要测试Context
位图加载功能,因为我确信它已经在Android框架中进行了测试。您已经对工厂模式有了一个好主意,因为您可以在应用程序中使用myClass(bitmapFactory)
并在测试中使用myClass(mockFactory)
注入模拟工厂进行测试。
如果您完全确定需要编写测试来覆盖位图加载,那么请查看像robolectric这样的测试框架,因为它可以为这样的场景提供模拟上下文。
答案 1 :(得分:1)
如果您需要Context
的功能,那么您需要以某种方式将其传递给MyClass
。但是,这并不意味着您需要静态存储Context
。事实上,这将是一个非常糟糕的设计选择(看起来你已经知道了)。
如果您使用Dagger,那么我有this video教程,解释如何构建依赖注入代码。这种结构的一部分确实处理了Context
对象的复杂性。
现在,即使MyClass
需要访问Context
才能获取位图,但这并不意味着您需要解决集成测试问题。
首先,您可以使用Robolectric - 这个库"模拟" Android框架,我认为它支持从资源中获取位图。
但是,根据您的使用情况,还有一个更简单的选项。您真的需要特定的位图,或者您只是想确保MyClass
对此位图执行特定操作吗?
如果你需要你作为资源添加的特定的那个,那么去Robolectric,但如果没有,你需要的只是确保正确使用获得的位图,那么你可以只是模拟位图。
为了提高可读性,简化测试并防止违反Demeter法,我建议你将Context
包装到这个类中:
public class BitmapRetriever {
private final Context mContext;
public BitmapRetriever(Context context) {
mContext = context;
}
public Bitmap getBitmapById(int id) {
// code that obtains bitmap
}
}
然后让MyClass
取决于BitmapRetriever
而不是Context
。
执行此操作后,可以直接在测试中传递模拟BitmapRetriever
,当Bitmap
要求时,将返回模拟MyClass
。然后你可以在那个模拟上断言各种条件。