Unity用MockClientの話

1d1580fb0945b0ffadff18e28bead3c5?s=47 いも
June 19, 2018

 Unity用MockClientの話

弁当付き社内LT「Jikai Lightning Talks #1」で発表したやつを公開用にちょっと修正したやつです

1d1580fb0945b0ffadff18e28bead3c5?s=128

いも

June 19, 2018
Tweet

Transcript

  1. Unity 用MockClient のお話 2018/06/19 Jikai Lightning Talks #1

  2. imo です

  3. 最近やったこと テスト導入したりしていました。 https://speakerdeck.com/adarapata/unitypurodakut onitesutowodao-ru-siteikumade?slide=1

  4. 最近困っていたこと ユニットテストは導入できたが書けないパター ン がある 通信とか挟まるとダメ 通信の結果ごにょごにょとかよくある 通信テスト自体はエディタ拡張している つらい

  5. どう解決するか? ユニットテスト時のみモックしてくれる仕組みが 欲しい Unity にそういう機能はないっぽい 通信をモックするクライアントを実装しよう

  6. API Client の流れ APIClient にRequestBase を投げると通信してくれる var client = new

    ApiClient(); client.StartRequest(new FooRequest()); // => Result<FooResponse>
  7. 抽象化してみる IHTTPClient を差し替えれればスマー トっぽい でも結構根っこから変えるのは大変そう IApiClient <=> IRequest 間をごまかそう

  8. どうモックするか Moq を利用する https://github.com/moq/moq4 C# 用のモックライブラリ Zenject にOption として付属している .NET

    3.5 用と4.6 用どちらも用意してて便利
  9. できあがり テスト用に ApiClientMock クラスを作成。 Mock メソッドでモックできる var mock = new

    ApiClientMock(); var mockResponse = new TResponse(); mock.Mock<TRequest, TResponse>().Success(mockResponse); mock.StartRequest(new TRequest()); // => Result<TResponse>
  10. 通信が成功したことにする var mock = new ApiClientMock(); var response = new

    FooResponse(); mock.Mock<FooRequest, FooResponse>().Success(response); var result = mock.StartRequest(new FooRequest()); result.Response.Content; // => FooResponse
  11. サー バからエラー が返ってきたことにする var mock = new ApiClientMock(); ErrorResponse error

    = new ErrorResponse(); mock.Mock<FooRequest, FooResponse>().Failure(error); var result = mock.StartRequest(new FooRequest()); result.Response.ErrorResponse; // => ErrorResponse
  12. 通信エラー が発生したことにする var mock = new ApiClientMock(); mock.Mock<FooRequest, FooResponse>().Error(Error.Network); var

    result = mock.StartRequest(new FooRequest()); result.ErrorCause; // => Error.Network
  13. バリデー ション モックしてない部分の通信が走ると落ちる => FooRequest はモックされていません。 ex. client.Mock<FooRequest, FooResponse>().Success(res); モックしたレスポンスが適切でなかったら落ちる

    => レスポンスが間違ってます Expected: <FooReponse> But was: <BarResponse> モックしたけど呼ばれなかったら落ちる => FooRequest をモックしましたが呼ばれていません!
  14. 用途 通信の結果で処理が変わるFooUseCase を想定 public class FooUseCase { private IApiClient client;

    public FooUseCase(IApiClient client) { this.client = client; } public string Run() { var result = client.StartRequest(new FooRequset()); if(result.IsSuccess) { return result.Response.Content.Foo; } else { return "NG"; } } }
  15. テストコー ド public class FooUseCaseTest { private IApiClient client; [Test]

    public void Run_Success() { client = new ApiClientMock(); var response = new FooResponse { Foo = "OK" }; client.Mock<FooRequest, FooReponse>() .Success(response); var useCase = new FooUseCase(client); Assert.AreEqual("OK", useCase.Run()); } } ApiClientMock を外から流し込めば意図した挙動にな る
  16. Moq 便利 通信部分を気にせずテストが書ける 「 これテスト書けますよ!」 というアプロー チが しやすくなった モックのやり過ぎに注意 テストしないといけない部分をモックしては本末

    転倒 何故モックするのかを考える 通信そのものは別でテストしましょう