1. ホーム
  2. database

[解決済み] データベースクエリを使ったオブジェクトのユニットテスト方法

2022-04-29 02:39:08

質問

しかし、私のファイルの70%以上はデータベースへのアクセス(一部は読み込み、一部は書き込み)を含んでおり、これらのファイルのユニットテストをどのように書けばよいのかわかりません。

私はPHPとPythonを使用していますが、データベースアクセスを使用するほとんどの/すべての言語に当てはまる質問だと思います。

どのように解決するのですか?

データベースへの呼び出しをモック化することをお勧めします。 モックとは、基本的に、メソッドを呼び出そうとしているオブジェクトに似ているオブジェクトのことで、呼び出し元が利用できるプロパティやメソッドなどが同じという意味で、モックと呼びます。 しかし、特定のメソッドが呼び出されたときに行うようにプログラムされているアクションを実行する代わりに、それを完全にスキップして、ただ結果を返します。この結果は、通常、前もって定義しておく。

モッキングのためにオブジェクトをセットアップするには、おそらく次の疑似コードのように、ある種の制御の逆転や依存性の注入パターンを使用する必要があります。

class Bar
{
    private FooDataProvider _dataProvider;

    public instantiate(FooDataProvider dataProvider) {
        _dataProvider = dataProvider;
    }

    public getAllFoos() {
        // instead of calling Foo.GetAll() here, we are introducing an extra layer of abstraction
        return _dataProvider.GetAllFoos();
    }
}

class FooDataProvider
{
    public Foo[] GetAllFoos() {
        return Foo.GetAll();
    }
}

ユニットテストでは、FooDataProvider のモックを作成し、実際にデータベースを叩くことなく GetAllFoos メソッドを呼び出せるようにします。

class BarTests
{
    public TestGetAllFoos() {
        // here we set up our mock FooDataProvider
        mockRepository = MockingFramework.new()
        mockFooDataProvider = mockRepository.CreateMockOfType(FooDataProvider);

        // create a new array of Foo objects
        testFooArray = new Foo[] {Foo.new(), Foo.new(), Foo.new()}

        // the next statement will cause testFooArray to be returned every time we call FooDAtaProvider.GetAllFoos,
        // instead of calling to the database and returning whatever is in there
        // ExpectCallTo and Returns are methods provided by our imaginary mocking framework
        ExpectCallTo(mockFooDataProvider.GetAllFoos).Returns(testFooArray)

        // now begins our actual unit test
        testBar = new Bar(mockFooDataProvider)
        baz = testBar.GetAllFoos()

        // baz should now equal the testFooArray object we created earlier
        Assert.AreEqual(3, baz.length)
    }
}

よくあるモッキングシナリオを簡単に説明します。 もちろん、実際のデータベース呼び出しもユニットテストしたいでしょうし、そのためにはデータベースを叩く必要があります。