Java 我应该如何处理DI和测试的上下文对象?
我有一个创建位图对象的类 它需要访问位图资源,所以它需要访问我传递给它的构造函数的上下文,所以我像myClass(context) 理想情况下,我希望以某种方式注入依赖项。我想用一个工厂来实现这一点,这样我就可以向工厂请求对象,它会为我创建对象,但我只能从创建新窗口的活动类中获取上下文。因此,看来我必须在我主要活动的背景下继续传递 我最近问了一个类似的问题,他们告诉我根本不应该静态地调用上下文,应该始终传递上下文 这意味着如果我想测试这个类,我的测试类需要访问android框架(这意味着我不能在本地测试,必须使用AndroidTests)Java 我应该如何处理DI和测试的上下文对象?,java,android,unit-testing,android-studio,android-context,Java,Android,Unit Testing,Android Studio,Android Context,我有一个创建位图对象的类 它需要访问位图资源,所以它需要访问我传递给它的构造函数的上下文,所以我像myClass(context) 理想情况下,我希望以某种方式注入依赖项。我想用一个工厂来实现这一点,这样我就可以向工厂请求对象,它会为我创建对象,但我只能从创建新窗口的活动类中获取上下文。因此,看来我必须在我主要活动的背景下继续传递 我最近问了一个类似的问题,他们告诉我根本不应该静态地调用上下文,应该始终传递上下文 这意味着如果我想测试这个类,我的测试类需要访问android框架(这意味着我不能在
这就是它的工作原理吗?我的类只需要一个位图,但由于上下文关系,我现在无法在本地进行测试。如果你的类只需要一个位图,为什么你不能模拟一个位图?你应该在课堂上测试逻辑。您不需要测试
上下文
位图加载功能,因为我确信它已经在Android框架中测试过了。您已经对工厂模式有了很好的想法,因为您可以通过在应用程序中使用myClass(bitmapFactory)
和在测试中使用myClass(mockFactory)
注入模拟工厂进行测试
如果您完全确定需要编写一个测试来覆盖位图加载,那么请查看测试框架,因为它可以为类似这样的场景提供模拟上下文。如果您需要
上下文的功能,那么您需要以某种方式将其传递到MyClass
。但是,这并不意味着您需要静态存储上下文。事实上,这将是一个非常糟糕的设计选择(看起来你已经知道了)
若您使用Dagger,那个么我有一个教程解释了如何构造依赖注入代码。这种结构的一部分实际上是处理上下文
对象的复杂性
现在,即使MyClass
需要访问Context
才能获得位图,也不一定意味着您需要解析集成测试
首先,您可以使用Robolectric——这个库“模拟”Android框架,我认为它支持从资源中获取位图
然而,根据您的用例,还有一个更简单的选项。您真的需要一个特定的位图,还是只想确保MyClass
在此位图上执行特定操作
如果您需要添加为资源的特定位图,请选择Robolectric,但如果不需要,则只需确保正确使用获得的位图,即可模拟位图
为了提高可读性、简化测试并防止违反Demeter定律,我建议您将上下文
包装到此类中:
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
一旦您这样做,就可以直接通过测试中的mockedBitmapRetriever
,当MyClass
请求时,该测试将返回mockedBitmap
。然后,您可以在该模拟上断言各种条件。这很有趣,但使用单独的位图检索器如何使测试更容易。@red888,它归结为单一责任原则。如果您的类接受上下文,那么理论上它可以访问其所有方法。你知道它只使用其中的一个,但是在你之后工作的人(或者六个月后的你自己)不会知道这一点。此外,将上下文传递到任何类都会破坏封装。通过将其包装到一个只负责一项任务的类中,您可以简化代码的读取和测试的编写,并消除将来有人也开始使用其他上下文方法的可能性。@red888,简而言之-如果您的类只需要位图,则没有理由让它访问整个上下文。这被称为违反德米特定律。@red888,更多关于单一责任原则和上下文:如果我用工厂构建myClass,我还会将上下文传递给创建对象的工厂吗?我想我必须这样做,因为我不能让工厂成为一个活动类,对吗?另外,为什么在上下文包装器中使用“final”?