wkwk_soprano’s blog

wkwkのメモです

【メモ】 単体テストとinternalメソッド

publicにはしたくないけれどもテストをしたいメソッドの処遇をどうするべきか 例えばユーザの住所を登録するクラスをpublicとprivateのメソッドからなる以下のような処理で書いたとする

public class UserAddress
{
    public void Register(string address)
    {
        var detailedAddress = AddressDetails(address);
        (DBに登録する処理)
    }

    private AddressDetails DecomposeAddress(string address)
    {
        var addressDetails = new AddressDetails
        {
            (住所をAddressDetailsに入るよう分割する処理)
        };
        return addressDetails;
    }
}

public class AddressDetails
{
    public string PostalCode { get; set; }
    public string Prefecture { get; set; }
    public string City { get; set; }
}

ここでDecomposeAddressへ入力する住所が不正なときに想定した挙動になっているかテストしたいのだが、privateのままだと単体テストができない(Reflectionとやらを使ったらできるとのことだが、今回の話からそれるので今は触れない) しかしながらこのクラス自体は「(ユーザから)住所の文字列を受け取って(DBへ)登録する」という責務で作られているため、DecomposeAddressメソッドを外部に向けて公開する必要がない

C#の場合、このprivateメソッドをinternalにすることでテスト用のプロジェクトからアクセスできるようにするという方法を取れるらしい 具体的にはinternalなクラスをテストする場合、 [assembly: InternalsVisibleTo("テストのアセンブリ")] というアトリビュートをクラスのあるファイル内に記述するとそのように設定できるとのこと(こちらの記載より)

このような方法がとれるのであれば、テストしたいような詳細は最初からinternalで書いてしまえばよい気がしている 実際こちらのStack Overflowの回答をみているとinternalクラスはテストされるべきで、またこちらのdiscussionからするとテストされるべき詳細はinternalで書くべきという主張を確認できる ※「テストされるべき詳細はinternalで書くべき」は本文からすると言いすぎかもしれない

InternalsVisibleToのアトリビュートを使えばテスト以外のアセンブリからも参照することは可能だが、それをしたいならそもそもpublicにすればよいだけなので、あくまで開発上は使いたいけど公開したくないようなクラス・メソッドに対して使うのがいいのかなと感じた