質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.36%

  • C#

    4749questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • WPF

    516questions

    Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

  • MVVM

    57questions

    MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

単体テストにおけるスタブ、ドライバの作成方法

解決済

回答 1

投稿 2017/12/06 15:44

  • 評価
  • クリップ 0
  • VIEW 85

---t---

score 25

表題の件で質問させてください
現在アプリを作成し、単体テストを行っています
その中でスタブを使いたい部分が出てきたのですが、調べかたが悪いためかドライバやスタブの概要は記載されていても実装の仕方がわからず、そもそもそういうクラスがあるのか、実装にあたって何か特殊な記載方法があるのかどうかすらわからず悩んでおりアドバイスをいただきたいです

以下現在取り組んでいる内容です
MVVMにおけるModelクラスの構造が以下のような流れになっています

Model① 
↓(①で加工されたデータを引数で渡しModel②のメソッドを呼び出す)
Model②
↓(②で加工されたデータを引数で渡しModel③のメソッドを呼び出す)
Model③
(①②で加工されたデータを受け取り最終加工)

知識が浅いためこのような構造になっているのですが、Model①のテストを行うとModel③まで到達します
Model①クラスのみのテストを行うためにスタブを使えるといいのかなと考えています
もし考え方がおかしい部分があればご指摘いただけると幸いです
宜しくお願い致します

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

こんにちは。

正しいと思います。
Model1のテストをするにあたってはModel2以降はスタブを使ったほうが良いと思います。

ドライバについてVisual Studioに統合されているユニットテストの仕組みなどがその役割を果たしていると思います。
PrivateなアクセスについてはPrivateObjectが提供されているので直接アクセスすることが出来ます。

Microsoft Fakes や Moq などのライブラリを活用するとスタブ利用しやすいと思います。
そもそもDI出来るようにしておくのが望ましいですが。

投稿 2017/12/07 11:28

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/07 13:05

    回答ありがとうございます
    MoqやFakesなど初めて知りました
    インターフェースの理解が浅いのでまずはMoqを使用してみます
    (ラムダ式も理解できていませんが・・・)
    まずは”メソッドが”呼び出されたか”を目標にしてみます

    >>そもそもDI出来るようにしておくのが望ましいですが。
    まだまだ理解が浅くオブジェクト指向が何たるかも習得しきれていませんが やはりクラス間で処理が続いてしまうのはクラスを分けている意味がなく、良くないのですね

    キャンセル

  • 2017/12/07 13:50

    重ねての質問で申し訳ないのですが教えてください
    今回はModel1のテストを行う基準として、Model1内のsarch1というメソッドが実行されるとModel2のsarch2というメソッドに引数を渡して実行します。このため、Model1のテストではModel2のsarch2が呼ばれた、という事をテスト基準にしたいのですが、SetupをModel1.sarch1とした場合Returnには戻り値などはなく、単純にメソッドが呼ばれたことを確認するにはどのように記述すればよいでしょうか?Verifyを使うにもSetupで指定する必要があると理解したのですが間違えているでしょうか?コードも見せずに質問して答えにくいと思いますが、よろしければアドバイスお願いいたします

    キャンセル

  • 2017/12/07 14:02

    Setup時にVerifiableを指定してVerifyで良いと思います。

    https://insimpleterms.blog/2017/07/12/moqs-setup-verify-verifiable-and-callback-methods/

    キャンセル

  • 2017/12/08 10:02

    ありがとうございます
    引数等は省略していますが以下のコードで実装出来ました
    ただ、一部理解があっているのか確認させていただいてもよろしいでしょうか
    コードや定義が分からない状態で申し訳ありません

    このテストメソッドはModel1クラスのテストです
    自分で書いたのですが特に②、③の理解があっているのかあいまいです
    ③に関してはvar field = sarch.GetField("model2")で初めは書いたのですがエラーとなったため書き直したのですが
    これはMockで指定しているModel2と紐付いていないためでしょうか?


    ---確認したい箇所---

    ①Mock<Model2> mock = new Mock<Model2>();
    ・Model2クラスのモックを作成

    ②var sarch = new PrivateObject(_model1);
    ・_model1(Model1のクラスのインスタンス)内にあるPrivateオブジェクトをsarchを用いて使用出来るようにする

    ③sarch.SetFieldOrProperty("model2", mock.Object);
    ・sarch.SetFieldOrProperty(_model1のPrivateオブジェクト利用権利のようなもの?)でmodel2というPrivateオブジェクト
    をmock(Model2クラスのモック)で使用できるようにする
    ※model2はModel1クラスが持っているModel2クラスインスタンスです

    ④_sarch1.sarch1();
    テスト対象のメソッド実行

    ⑤mock.Verify(x => x.SarchCheck2_1(), Times.Once());
    mock.Verifyで④_sarch1.sarch1();の処理から呼ばれるはずのModel2クラスのSarchCheck2_1()が一度呼ばれたかどうか確認



    ---以下コード---

    Model1 _model1 = new Model1();
    Model2 _model2 = new Model2();

    [TestMethod()]
    public void sarch1Test()
    {
    ①Mock< Model2> mock = new Mock< Model2>();

    ②var sarch = new PrivateObject(_model1);

         ③sarch.SetFieldOrProperty("model2", mock.Object);
         //var field = sarch.GetField("model2")

    ④_sarch1.sarch1();
    ⑤mock.Verify(x => x.SarchCheck2_1(), Times.Once());

    }


    ①Mock<Sarch2> mock = new Mock<Sarch2>();
    Sarch2クラスのモックを作成

    ②var sarch = new PrivateObject(_sarch1);
    _sarch1(Sarch1のクラスのインスタンス)


    Sarch1 _sarch1 = new Sarch1();
    Sarch2 _sarch2 = new Sarch2();

    [TestMethod()]
    public void sarch1Test()
    {
    ①Mock<Sarch2> mock = new Mock<Sarch2>();

    ②var sarch = new PrivateObject(_sarch1);

         ③//var field = sarch.GetField("sarch2");
    ③//sarch.SetFieldOrProperty("sarch2", mock.Object);


    ④_sarch1.sarch1();
    ⑤mock.Verify(x => x.SarchCheck2_1(), Times.Once());

    }

    キャンセル

  • 2017/12/08 10:14

    確認したい事の項目のコードの下に書いてる・から始まる部分が自分の今の理解です

    キャンセル

  • 2017/12/08 15:57

    クラス名とメソッド名が混在しててよくわからないですね…。
    PrivateObjectを使っているのはなぜですか?

    Model2はプロパティか、コンストラクタなどでインジェクションできるようにしておいたほうがテストしやすいですよ。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.36%

関連した質問

  • 解決済

    Laravelのリポジトリパターン

    Laravelのリポジトリパターンについて勉強中です。 わからないことがあるのでご教授下さい。 以下のようなスキーマがあるとします。 User - id, user_name, 

  • 解決済

    [至急] jarファイルを実行時にPostgreSQLを利用できない

    いつもお世話になっております。 仕事上、どうしても解決できない事案が発生してしまったので、質問させていただきます。 現在、eclipse4.2を利用して、windows上で動くア

  • 解決済

    JAVA DOCを自動生成してくるツールはありますか?

    eclipsで、 JAVAでプログラムを書いているのですが、 JAVA DOCの存在をしらなくて、書いていないのですが、 30本くらいあるJAVAソースへ一括で、もしは、一つのソ

  • 解決済

    モックとスタブの違いについて

    モックとスタブの違いについて教えてください。職場で、スタブを使って意図的に画面上でエラーを発生させ、それをフィルタリングできているかどうかのテストをしたのですが、スタブが何かわかっ

  • 解決済

    C#でWeb作成のエラーメッセージに困っています...

    C#でWeb作成している初心者です。 現在、Visual studio 2015にて、練習でWebページを作成しております。 MVCで作成をしております。 ビュー上で"ID"

  • 受付中

    cakePHPで共通関数を書く場合のcomponentとbehaviorの住み分けについて

    cakePHP1.3です。 Controller、Modelの両方でよく使用される共通関数があるとします。 共通化するために、最初はcomponentに書いていおり、Model

  • 解決済

    モデルの書き方

    <?php class Model_insert extends CI_Model{ public function __construct(){

  • 解決済

    PHP 処理の分け方

    はじめに 今回は、プログラムのコード等に関する質問ではありません。 当然、今回の質問に対して状況や考え方など正解という正解もなく、また不正解ということもないのは理解しております。

同じタグがついた質問を見る

  • C#

    4749questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • WPF

    516questions

    Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

  • MVVM

    57questions

    MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。