2017-02-08 3 views
0

私は簡単なゲームを作っており、モデルのセットアップやテストについていくつか質問しています!可能であればMVPパターンに従おうとしています。簡単なゲーム設定でAndroidモデル(MVP)を正しくテストするにはどうすればよいですか?

以下は、私のモデルクラスの一部を簡略化したもので、主に「ロジック」を扱っています。

public class GameManager implements LocationManagerDelegate { 

    private LocationManager mLocationManager; 
    private BattleManager mBattleManager; 

    public GameManager(Location initialLocation) { 
     mLocationManager = new LocationManager(initialLocation, self); 
     mBattleManager = new BattleManager(); 
    } 

    public void setLocation(Location location) { 
     mLocationManager.setLocation(location); 
    } 

    public void handleLocationAction(Action action) { 
     if (action.type == BATTLE) { 
      mBattleManager.startBattle(); 
     } 
    } 
} 

public class LocationManager { 

    private LocationManagerDelegate mDelegate; 
    private Location mLocation; 

    public LocationManager(Location initialLocation, LocationManagerDelegate delegate) { 
     mLocation = initialLocation; 
     mDelegate = delegate; 
    } 

    public void setLocation(Location location) { 
     mLocation = location; 

     Action action = location.getRandomAction(); 

     mDelegate.handleLocationAction(action); 
    } 
} 

public interface LocationManagerDelegate { 
    void handleLocationAction(Action action); 
} 

public class BattleManager { 

    public BattleManager() { 
    } 

    public void startBattle() { 
     // Do stuff... 
    } 
} 

これらのクラスを正しくテストすることに興味があります。彼らは別のもので、必要な場合、私は代表団のためのモックインタフェースを使用することができます(つまりLocationManagerDelegate

しかし、何GameManagerについて - 私は簡単にLocationManagerBattleManagerをテストすることができますか?具体的なLocationManager/BattleManagerのインスタンスをそれ自身のクラスに作成するので、GameManagerを使用してクラスからロジックの全体的なフローをテストしたい場合は、実際にGameManagerLocationManager/BattleManagerというロジックをテストします。私はそれを分割するきれいな方法を見つけることができません...

これはもっと正しいでしょうか?

public class GameManager implements LocationManagerDelegate { 

    private ILocationManager mLocationManager; 
    private IBattleManager mBattleManager; 

    public GameManager(Location initialLocation, ILocationManager locationManager, IBattleManager battleManager) { 
     mLocationManager = locationManager; 
     mLocationManager.setInitialLocation(initialLocation); 
     mLocationManager.setDelegate(this); 

     mBattleManager = battleManager; 
     mBattleManager.setDelegate(this); 
    } 

    public void setLocation(Location location) { 
     mLocationManager.setLocation(location); 
    } 

    public void handleLocationAction(Action action) { 
     if (action.type == BATTLE) { 
      mBattleManager.startBattle(); 
     } 
    } 
} 

public interface ILocationManager { 
    void setInitialLocation(Location initialLocation); 
    void setDelegate(LocationManagerDelegate delegate); 
    void setLocation(Location location);  
} 

public class LocationManager implements ILocationManager { 

    private LocationManagerDelegate mDelegate; 
    private Location mLocation; 

    public void setInitialLocation(Location initialLocation) { 
     mLocation = initialLocation; 
    } 

    public void setDelegate(LocationManagerDelegate delegate) { 
     mDelegate = delegate; 
    } 

    public void setLocation(Location location) { 
     mLocation = location; 

     Action action = location.getRandomAction(); 

     mDelegate.handleLocationAction(action); 
    } 
} 

public interface LocationManagerDelegate { 
    void handleLocationAction(Action action); 
} 

public interface IBattleManager { 
    void startBattle(); 
} 

public class BattleManager implements IBattleManager { 

    public void startBattle() { 
     // Do stuff... 
    } 
} 

その後、我々は実際にGameManagerインスタンスを作成してどこに、我々のようなものを実行します。

ILocationManager locationManager = new LocationManager(); 
IBattleManager battleManager = new BattleManager(); 
Location initialLocation = ...; 

GameManager manager = new GameManager(initialLocation, locationManager, battleManager); 

をこれは私がLocationManager/BattleManagerモックオブジェクトに配置することが可能になるだけでなく、このため、大きすぎるではないかもしれませんGameManagerクラスの「内部動作」の一部を公開しています。必ずしも私がこれらの他のマネージャークラスなどで渡す必要がある公開情報である必要はありません。

それでは、どうすればよいですか?何かご意見は!あなたは上記のアウトラインとしてこれは、依存関係

1.コンストラクタ・インジェクション:

答えて

1

私はあなたがここに2つのオプションがありますと言うでしょう。依存関係は、クラス外で作成され、作成時に渡されます。このようにして、テスト時にあなたのモックを渡すことができます。これは、Daggerなどの依存性注入ライブラリを使用していた場合のやり方も同じです。

2.自体、彼らはプライベート変数をパッケージ化するためのアクセス権を持っているクラスと同じパッケージでのライブクラスのテストとして依存関係パッケージプライベート

してください。この場合、あなたは2つの依存関係のアクセスレベルを変更します:どちらの方法での内部を開くのトレードオフを持って

@Before 
public void setUp() throws Exception { 

    gameManager = new GameManager(); 
    gameManager.mLocationManager = locationMock; 
    gameManager.mBattleManager = battleMock; 
} 

public class GameManager implements LocationManagerDelegate { 

    LocationManager mLocationManager; 
    BattleManager mBattleManager; 

    //... 
} 

次に、あなたのテストから、あなたのような何かを行うことができますテスト対象のクラス個人的に私は現在、私のクラスが既にDIのために設定されているので、コンストラクタインジェクションを使用することを好みます。

関連する問題