web-dev-qa-db-ja.com

Moqを使用したメソッドのユニットテスト

C#とMoqを使用して単体テストを行う方法を学習しようとしていますが、少しテスト状況を構築しました。このコードを考えると:

_public interface IUser
{

    int CalculateAge();
    DateTime DateOfBirth { get; set; }
    string Name { get; set; }
}

public class User : IUser
{
    public DateTime DateOfBirth { get; set; }
    string Name { get; set; }

    public int CalculateAge()
    {
        return DateTime.Now.Year - DateOfBirth.Year;
    }
}
_

メソッドCalculateAge()をテストしたい。これを行うには、テストメソッドでこれを実行してDateOfBirthプロパティにデフォルト値を指定してみるべきだと思いました。

_var userMock = new Mock<IUser>();
userMock.SetupProperty(u => u.DateOfBirth, new DateTime(1990, 3, 25)); //Is this supposed to give a default value for the property DateOfBirth ?
Assert.AreEqual(22, userMock.Object.CalculateAge());
_

しかし、アサーションに関しては、CalculateAge()の値は0に等しくなりますが、DateOfBirthnew DateTime(1990, 3, 25)に等しくなります。

これはばかげた例のように見えるかもしれませんが、何でも...モックを使用して、オブジェクト内のまだ開発されていないメソッド/プロパティに値を与えることができると思ったので、メソッドのテストは別のコンポーネントに依存しません私のクラスの、または私のオブジェクトのデフォルトコンテキストを設定することさえあります(したがって、ここにユーザーの名前があります...)私はこの問題に間違った方法でアプローチしていますか?

ありがとう。

18
Pacane

はい、あなたはそれに間違ってアプローチしていますが、心配しないでください、私は理由を説明します。最初のヒントは

Userクラスを完全に削除すると、すべてが同じになります。

あなたがしているとき:

var userMock = new Mock<IUser>();

そのインターフェイスの偽の\ mockオブジェクトを作成するだけで、最初のUserクラスとは関係がないため、CalculateAgeメソッドの実装はありません。ただし、偽のオブジェクトは例外です。ばかげて0を返します。そのため、assertステートメントで0を取得しています。

だから、あなたは言っていました:

モックを使用して、オブジェクト内のまだ開発されていないメソッド/プロパティに値を与えることができると考えたので、メソッドのテストはクラスの別のコンポーネントに依存しません。

たとえば、IUserのコンシューマーがいるとすると、次のようになります。

class ConsumerOfIUser
{
   public int Consume(IUser user)
   {
      return user.CalculateAge() + 10;
   }
}

その場合、IUser.CalculateAge()が10を返したときにConsumerOfIUserがどのように動作するかをテストしたいので、IUserのモックは完全に理にかなっています。次のようにします。

var userMock = new Mock<IUser>();
userMock.Setup(u => u.CalculateAge()).Returns(10);

var consumer = new ConsumerOfIUser();
var result = consumer.Consume(userMock);

Assert.AreEqual(result, 20); //should be true
23
Restuta

それはあなたが何をテストしようとしているかによります。この場合、Userオブジェクトをモックアウトしているため、このクラスをモックオブジェクトに置き換えるため、このクラス内の何かをテストしても意味がありません。 Userオブジェクトをテストする場合は、モックアウトしないでください。

モックは、テストしたくない依存オブジェクトを置き換えるために使用されます。たとえば、文字列の代わりにNameオブジェクト(たとえば、名、姓、タイトルなどが含まれている)があり、Nameオブジェクトをテストしたくなく、Userオブジェクトだけをテストしたい場合は、のモックを作成します。 Userオブジェクトを作成するときに使用するオブジェクトに名前を付けます。

2
Ben