5

TCP を介してメッセージをやり取りすることにより、ゲーム同期サーバーとの通信を処理する Android サービスがあります。

このサービスの動作を単体テストできるようにしたいと考えています。つまり、ネットワーク上でデータが読み取られ、解析され、対応する有効なインテントが送信され、サービスがインテントを受信すると、サーバーに送信されるメッセージが正しく作成されます。

私は単体テストが特に得意ではありませんが、単体テストを練習の一部にしようとしています。このようなものにアプローチする方法がわかりません。どうにかしてソケットをモックアップし、入力ストリームと出力ストリームを偽造する必要があるように感じますが、特に Android に適用されるため、その方法が本当にわかりません。

これが(簡潔にするために大幅に削減された)サービスです。

public class GameSyncService extends Service {
    Thread mInputThread = new Thread() {

        /**
         * Parse commands from a message string, broadcast the command intents, and
         * return the remainder of the message
         * @param message The message to parse for commands
         * @returns the remaining characters
         */
        private String parseCommands(String message) {
            // Parse the command, Broadcast the Intent and return any remainder
        }

        @Override
        public void run() {
            String message = "";
            int charsRead = 0;
            char [] buffer = new char[BUFFER_SIZE];
            while(!Thread.interrupted()) {
                try {
                    while ((charsRead = mIn.read(buffer)) != -1) {
                        message += new String(buffer).substring(0, charsRead);
                        message = parseCommands(message);
                    }
                } catch (IOException e) {
                    Log.d(LOG_TAG, "Error receiving response: " + e.getLocalizedMessage());
                    disconnectFromServer();
                    connectToServer();
                }
            }
        }
    };

    private BroadcastReceiver mMessageSender = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String message = intent.getStringExtra("message");
            sendMessage(message);
        }

    };

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    private void sendMessage(String message) {
        new SendCommandMessageTask().execute(message);
    }

    /**
     * Create a new connection to the server
     */
    private void connectToServer() {
        try {
            if (mSocket == null) {
                mSocket = new Socket(mHost, mPort);
                mOut = new PrintWriter(mSocket.getOutputStream());
                mIn = new BufferedReader(new InputStreamReader(mSocket.getInputStream()), BUFFER_SIZE);
                sendMessage("Handshake:|" + pInfo.versionName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Disconnect from the server and reset the socket to null
     */
    private void disconnectFromServer() {
        if (mSocket != null) {
            try {
                mIn.close();
                mOut.close();
                mSocket.close();
                mSocket = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public int onStartCommand(Intent i, int flags, int startId) {
        Log.d(LOG_TAG, "GameSyncService Started");
        mHost = i.getStringExtra("host");
        mPort = i.getIntExtra("port", 9000);
        connectToServer();
        mInputThread.start();
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        registerReceiver(mMessageSender, new IntentFilter(COMMAND_MESSAGE_SEND_ACTION));
        try {
            pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(mMessageSender);
        super.onDestroy();
    }
}
4

2 に答える 2

2

嘲笑の世界へようこそ。あなたがする必要があることは、 Android Mockの助けを借りて簡単に行うことができます。Android Mockを使用したプロジェクトのライティング テストwiki ページで、Expectations が Android Mock でどのように機能するかを確認する必要があります。

私がすることは、基礎となる TCP/ソケット呼び出しをカプセル化するソケット サービスを実装することです。次に、Android Mock を使用して Socket サービスをモックし、Expectations を使用して、より高いレベルのメソッド ( GameSyncService など) によって正しいデータが渡されることを確認します。

于 2012-05-10T09:20:28.203 に答える
1

私は自分のプロジェクトでこの問題を発見しました。通常、構成クラスに実際の実装(この場合はソケットまたはモックしたいもの)またはモッククラスを挿入しようとします。

また、この構成クラスに特定のクラスのインスタンスを注入するのに役立つRoboguiceライブラリが非常に役立つこともわかりました。

Socket クラスを注入すると、構成クラスに移動し、定義したコンストラクターがインスタンス化されます。

@Inject Socket socket; //on your game class

bind(Socket.class).toInstance(socketImplentation); //on your Application class

これにより、@SetUp で、このテストでソケットのモック実装を使用するか、別のソケットでメッセージ モックを使用するかなどを定義できる Android テスト プロジェクトを作成できます。

それがアイデアに役立つことを願っています:)

于 2012-05-10T09:17:24.610 に答える