我用ShipFactory创建了船只对象,但我的船只依赖于我的Acclerometer类(只是android acclerometer的包装器)。因此,我建造一艘船时,我的工厂将加速度计传递给船舶构造商。
这是我的ShipFactory:
public class ShipFactory {
private int screenX;
private int screenY;
private Context context;
private Bitmap bitmap;
// How can I mock this from in my factory?
private Accelerometer accel;
private Ship ship;
public ShipFactory(Context context){
this.context = context;
accel = new Accelerometer(context);
}
public Ship makeShip(String shipType){
bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.myship)
ship = new Ship(context,screenX,screenY,bitmap,accel);
return ship;
}
}
所以我这样做了一艘船:
ShipFactory shipFactory = new ShipFactory(context);
ship = shipFactory.makeShip("enemy");
但是现在让我说我要整理我的船级,我想模仿这些依赖。上下文很容易被模拟,因为我可以将模拟上下文传递给我的工厂,但我的工厂仍然依赖于加速度计。
对于单元测试,我应该创建一个仅用于测试的新工厂吗?或者使用工厂的好处是在我的单元测试中我可以一起放弃工厂,并通过将我的模拟传递给船舶构造函数直接创建一艘新船。
答案 0 :(得分:3)
您的ShipFactory
取决于Ship
。但Ship
不依赖于ShipFactory
。独立于Ship
测试您的ShipFactory
。由于没有依赖性,因此不需要依赖注入。
现在,当您的工厂变大时,您应该专门为您的工厂编写测试。为了实现这一点,我建议在构造函数中提取所有依赖项并注入它们。您可以重载构造函数来帮助您:
// you can use this for convenience
public ShipFactory(Context context){
this(new BitmapProvider(context), new Accelerometer(context));
}
// use this for testing because you can provide mock versions
public ShipFactory(BitmapProvider provider, Accelerometer accel){
this.provider = provider;
this.accel = accel;
}
// wrapping BitmapFactory because it is a buncha static methods... aka a pain to mock
class BitmapProvider {
Context context;
public BitmapProvider(Context context){
this.context = context;
}
public Bitmap getBitmap(int resId){
return BitmapFactory.decodeResource(context.getResources(), resId);
}
}
答案 1 :(得分:2)
在您的代码中,您的Ship
类会公开一个公共构造函数,因此您不需要ShipFactory
来创建Ship
对象。请改用public Ship
构造函数并模拟依赖项。
答案 2 :(得分:1)
您可以从ShipFactory中删除显式的Accelerometer依赖项,并像处理Context对象一样将其传入。
1)创建一个AccelerometerFactory,在其构造函数中接受Context,生成Accelerometer
2)修改ShipFactory构造函数以接受Context和Accelerometer,或者您可以修改makeShip方法以接受Accelerometer。
现在您可以单独模拟Context和Accelerometer并将它们传递给ShipFactory。
public class AccelerometerFactory {
private Context context;
public AccelerometerFactory(Context context){
this.context = context;
}
public Accelerometer makeAccelerometer(){
return new Accelerometer(context);
}
}
public class ShipFactory {
private int screenX;
private int screenY;
private Context context;
private Bitmap bitmap;
private Accelerometer accel;
private Ship ship;
public ShipFactory(Context context, Accelerometer accelerometer){
this.context = context;
this.accel = accelerometer;
}
public Ship makeShip(String shipType){
bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.myship)
ship = new Ship(context,screenX,screenY,bitmap,accel);
return ship;
}
}
{// Calling code
AccelerometerFactory accelFactory = new AccelerometerFactory(context);
Accelerometer accel = accelFactory.makeAccelerometer(); // Note: Accelerometer class would have to be accessible here, not sure if this is the case for you
ShipFactory shipFactory = new ShipFactory(context, accel);
ship = shipFactory.makeShip("enemy");
}