戦略モデル


学習の動機.
public void race() {
    for(Car car : cars) {
        car.move(movable());
    }
}
ここに残っているコメントではなくCars#raceに残っているコメントです
この方法はドメインオブジェクトCarsの方法であるが,テスト不可能な構造であるようである.
Carsからランダムに分離すれば、テスト可能な構造を作成できると思いますが、試してみてください:)
私はこの部分をよく理解していません!これはテスト不可能な構造であることは理解できますが、なぜランダムをCarsから分離すればテストできるのか理解できません.항상 일정한 값이 나올 수 있게 하는 외부 라이브러리を使用する方法は、同様に戦略モデルに基づいている.
戦略モデルをより使いやすくするためのライブラリと考えられる
ウトコレベル1タスクでは、ライブラリを使用する必要性が感じられない場合があります.できるだけ直接実施する.
今コードからrace()を呼び出すと、各車が動いているか、動いていない可能性があるので、テストできません.
この方法がテストできない理由をどこで見つけますか?
これがCarsオブジェクトの内部にランダム値を作成する部分です.
では、どのようにしてテスト性を実現しますか?
実際のコードの実行時にランダムに進むことができ、テストの場合、常に前進または前進しなくてもよい場合は、テストを行うことができます.
この文章を読んで戦略パターンを考えると方法が見つかるはず
戦略モデル
ポリシーモード(strategy pattern)またはポリシーモード(policy pattern)は、実行時にアルゴリズムを選択できる動作ソフトウェア設計モードです.

Javaの多形性を利用すれば実現できるような気がします.
適用
まずはインターフェイスを作ろうレースゲームでNumberGeneratorインターフェースを作成します.
NumberGenerator
public interface NumberGenerator {

    int generate();
}
そしてmove()法はNumberGeneratorを因子とし、numberGenerator.generate()の結果から判断する.
すなわち、実際のアプリケーションにおけるgenerate()と、テスト環境におけるgenerate()とをそれぞれ実現すればよい.
RandomNumberGenerator
public class RandomNumberGenerator implements NumberGenerator {

    private static final int MAX_RANDOM_VALUE = 10;
    private static final Random random = new Random();

    @Override
    public int generate() {
        return random.nextInt(MAX_RANDOM_VALUE);
    }
}
これは実際のアプリケーションで使用されるジェネレータです.
MovableGenerator
public class MovableNumberGenerator implements NumberGenerator {

    @Override
    public int generate() {
        return 4;
    }
}
試験用発電機このMovableNumberGeneratorを因子として伝達すると、moveになる可能性があります.どうしてもテスト用なので、テストバッグに入れるべきです.
NonMovableGenerator
public class NonMovableGenerator implements NumberGenerator {

    @Override
    public int generate() {
        return 3;
    }
}
このNonMovableNumberGeneratorを因子として伝達すれば、常にmoveであることは不可能である.
テストはランダムではありません.何を伝えるかによって、直接コントロールできます.
CarTest
class CarsTest {

    @DisplayName("각 차들이 모두 움직인다")
    @Test
    public void race() {
        ...

        cars.race(new MovableNumberGenerator());

        assertThat(cars.getParticipantCars())
                .filteredOn(car -> car.isSamePosition(nonMoveCar))
                .isEmpty();
    }
残りの懸念
このモードを適用すると、疑問があります.現在、私のコードはCarsrace()のうちRandomNumberGeneratorを引数として実現しています.この伝達部分はRacingControllerです.これではRacingController部分ではテストが難しくなります(RandomNumberGeneratorを伝えているので).責任逃れみたいな感じでちょっと気分が悪い
いい質問です皆さんにこのコメントに答えることもできますランダムオブジェクトの作成をCarsから親に移動するように、親に移動することもできます.RacingControllerの作成者からオブジェクトを取得すればよいでしょう.
アプリケーションでオブジェクトを作成するのはおかしいと思うかもしれませんが、このセクションではこのフェーズをスキップできます.私たちはウトコの2級ぐらいでこの問題がどのように解決されたのかを確認することができます.
もし2級でこの問題に遭遇したら、私はまた補充して書きます.
ソースとコメント
メソッドフラグを変更してテストしやすい方法にする
インタフェースを分離し、テストしやすい方法にします。
戦略モデル