Help us understand the problem. What is going on with this article?

【PHPUnit】スタブとモック

  • スタブとモックがよくごっちゃになる

毎回「これで合ってたっけ...?」と不安になって調べてるので、覚書です。

テストダブル

テストのための代用品のこと。

スタブ

テスト対象の関数の中で呼び出される、別の関数のテストダブルのこと。
スタブを作成する目的は想定する値を返させるため。

testdouble (4).png

テストしたい関数Aがある。
関数Aの中で使用される関数Bがあるとする。

testdouble (1).png

関数Aのテストをするとき、関数Bのテストを同時に行う必要はありません。
関数Bの処理のテストは、あくまで関数Bのテストで行います。

testdouble (3).png

このとき、関数Bに求められるのは「この入力でこの値を返す」ということだけです。
したがって、関数Bは期待した値を返すだけのスタブにしてしまっても
関数Aの処理の内容はテストできる、ということになります。

モック

テスト対象の関数の中で呼び出される、別のクラスのテストダブルのこと。
モックを作成する目的は

  • モック化したクラスの関数が呼び出されることをテストすること
  • モック化したクラスの関数が想定する値を返すようにすること
<?php
use PHPUnit\Framework\TestCase;

class SubjectTest extends TestCase
{
    public function testObserversAreUpdated()
    {
        // Observer クラスのモックを作成します。
        // update() メソッドのみのモックです。
        $observer = $this->getMockBuilder(Observer::class)
                         ->setMethods(['update'])
                         ->getMock();

        // update() メソッドが一度だけコールされ、その際の
        // パラメータは文字列 'something' となる、
        // ということを期待しています。
        $observer->expects($this->once())
                 ->method('update')
                 ->with($this->equalTo('something'));

        // Subject オブジェクトを作成し、Observer オブジェクトの
        // モックをアタッチします。
        $subject = new Subject('My subject');
        $subject->attach($observer);

        // $subject オブジェクトの doSomething() メソッドをコールします。
        // これは、Observer オブジェクトのモックの update() メソッドを、
        // 文字列 'something' を引数としてコールすることを期待されています。
        $subject->doSomething();
    }
}
?>

サンプルコードはPHPUnitの公式ページから拾ってきました。
Subjectクラスのテストにおけるモックの使い方について、順番に見ていきます。

モックの準備

        $observer = $this->getMockBuilder(Observer::class)
                         ->setMethods(['update'])
                         ->getMock();

モックを使う場合、まずはモックの作成が必要になります。

  • getMockBuilderを使って、Observerクラスのモックを作成
  • setMethodsで、モック化したクラスのupdateメソッドを置き換える
  • getMock()で作成したモックを取得

ここまでがモックの準備です。

モックの設定

        $observer->expects($this->once())
                 ->method('update')
                 ->with($this->equalTo('something'));

このテスト内でのモック化したクラスの振る舞いを決めます。

  • expects モックが呼び出される回数は1回であること
  • method モックから呼び出されるメソッドはupdateであること
  • with 引数として渡される値はsomethingと一致すること

モックを使ったSubjectクラスのテスト

        $subject = new Subject('My subject');
        $subject->attach($observer);
        $subject->doSomething();

モックを使わないテストと同様に、Subjectクラスからオブジェクトを作成します。
attachで作成したモックである$observer$subjectに設定します。
doSomethingメソッドを呼び出します。

参考にしたページ

8.テストダブル — PHPUnit latest Manual
https://phpunit.readthedocs.io/ja/latest/test-doubles.html?highlight=attach#test-doubles-mock-objects-examples-subjecttest-php

PHPUnitのモックオブジェクトの使い方を仕組みから理解する – たいさブログ
https://taisablog.com/archives/55

モックと、スタブとドライバと… | 石崎智展のWEB技術研究所
http://www.ishizaki-me.com/?p=1454

[PHP] PHPUnitのスタブとモックの違いとは – 端くれプログラマの備忘録
https://www.84kure.com/blog/2015/10/03/php-phpunit%E3%81%AE%E3%82%B9%E3%82%BF%E3%83%96%E3%81%A8%E3%83%A2%E3%83%83%E3%82%AF%E3%81%AE%E9%81%95%E3%81%84%E3%81%A8%E3%81%AF/

モックオブジェクトを利用したテスト - pixiv inside [archive]
https://devpixiv.hatenablog.com/entry/2014/12/11/192708

Test DoubleとPHPUnit | akkunchoi@github
http://akkunchoi.github.io/test-double-phpunit.html

PHPUnitをもう少し – Simple IT Life
https://simple-it-life.com/2016/02/26/phpunit-more1/

PHPUnit 入門 - Qiita
https://qiita.com/tsuuuuu_san/items/46246168dc36ad2369cc

PHPUnitでmockした関数の引数を指定する方法 - Qiita
https://qiita.com/sssinsi/items/878d9731cdc0bdd97ed5

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away