web-dev-qa-db-ja.com

データベースに依存する機能をテストする方法は?

ユーザーがアプリケーションに既に存在するかどうかをチェックするこの関数を書きました:

async function ValidateUserExists(username, email){
    if(!username || !email) throw new Error('Invalid number of args passed. Please pass username and email');
    let taken_valid_username = null;
    let taken_valid_email = null;
    if(username){
        taken_valid_username = await UsernameExists(username);
    }
    if(email){
        taken_valid_email = await EmailExists(email);
    }

    if(taken_valid_username) return taken_valid_username;
    if(taken_valid_email) return taken_valid_email;

    return null;
}

UsernameExists()とEmailExists()が正しく機能することを証明する統合テストがあります。

その主な目的は、ユーザーが既にデータベースに存在するかどうかを確認することです。 UsernameExists()とEmailExists()の両方がデータベースにアクセスして、ユーザーが実際に存在するかどうかを確認するように設計されているため、ここで何かをあざけることはできません。

データベースを操作することを主な目的とするアプリを構築しているとき、私はこのような多くの機能を持っています。つまり、統合テストがたくさん発生しています。

これまでのところ、私が書いたテストは次のようになります。

it('should see if a user already exists on an existent email', async ()=>{
    const test = await CreateDummyUser();
    const user = await ValidateUserExists(test.username, test.email);
    //expect user properties here
    await DestroyDummyUser(test);
})

このような複合関数を攻撃するために誰かが行ったモック/スタブへのアプローチはありますか?関数がパスで構成されるのに十分ですか?

3
KAT

多くの場合、答えは、必要な機能を引数として新しい関数に渡すことができるように設計を変更してから、困難なものを置き換える「ダブルテスト」で新しい関数をテストすることです。

async function ValidateUserExists(username, email){
    return ValidateUserExistsV2(username, email, UsernameExists, ValidateUserExists);
}

async function ValidateUserExistsV2(username, email, usernameExists, validateUserExists) {
    if(!username || !email) throw new Error('Invalid number of args passed. Please pass username and email');

    let taken_valid_username = null;
    let taken_valid_email = null;

    if(username){
        taken_valid_username = await usernameExists(username);
    }
    if(email){
        taken_valid_email = await emailExists(email);
    }

    if(taken_valid_username) return taken_valid_username;
    if(taken_valid_email) return taken_valid_email;

    return null;
}

ValidateUserExistsV2はテストが簡単です。テストでusernameExistsvalidateUserExistsの簡単な実装を定義できるためです。これらの実装は、データベースへの呼び出しを模倣する動作を提供します。

古い関数のテストは、単体テストスイートから外れます。リスクのほとんどは、新しい機能のテストによって処理されます。 ValidateUserExistsは、「コードレビューでテストできるほど単純であると見なされる場合がありますが、それが選択肢ではない場合でも、テストが少なくてリスクを軽減できるほど十分に単純です。

4
VoiceOfUnreason

関数の下にあるデータベース接続のみをモックする必要があります。

依存性注入(またはサービスロケータ)を使用している場合は、データベース接続をモック接続と簡単に交換できます。

0
tom6025222