web-dev-qa-db-ja.com

テスト用のメソッドを模擬

別のメソッド内で呼び出されたメソッドをモックしようとしています。

public virtual bool hello(string name, int age)
{

    string lastName = GetLastName();
}

 public virtual string GetLastName() 
    {
        return "xxx"; 
    }

 Mock<program> name= new Mock<program>();
 name.Setup(x => x.GetLastName()).Returns("qqq");

GetLastNameメソッドが常に「qqq」を返すようにしたいのですが。

9
codeislife

これらは完全なメソッド実装であると想定して、これは機能するはずです

public class MyProgram
{

    public bool hello(string name, int age)
    {
        string lastName = GetLastName();

        return string.Format("hello {0}", lastName);
    }

    public virtual string GetLastName() 
    {
        return "xxx"; 
    }
}

public class MyProgramTests
{

    [TestMethod]
    public void MyTest()
    {

        string stringToReturn = "qqq";
        Mock<MyProgram> name = new Mock<MyProgram>();
        name.CallBase = true;
        name.Setup(x => x.GetLastName()).Returns(stringToReturn );

        var results = name.Object.hello(It.IsAny<string>(), It.IsAny<int>());

        string expected = string.Format("hello {0}", results);

        Assert.AreEqual(expected, results);
    }
}

私はまだあなたのコメントを完全にはフォローしていません:

モックのパラメータは本当に何を意味するのでしょうか? ?すみません、構文がよくわかりません。明確にするために、モックとは、コードにブレークポイントを配置するときに、モックしているメソッドをブレークポイントがスキップすることを意味します。私は正しいですか?

Mock<T>を使用すると、Tのタイプをモックすることができます-Tは一般的なインジケーターであり、クラスのほとんどすべてのものを意味します。従来の方法では、実際のinterfaceではなくclassをモックしますが、上記の例では、クラスをモックしています。投稿されたサンプルの単体テストの場合、単体テストの目的はhello(string, int)の実装をテストすることです。 hello(string, int)は、そのクラス内のGetLastName()と呼ばれる別のメソッドに依存していることがわかっています。 GetLastName()の実装は重要ですが、単体テストの範囲にとっては重要ではありませんhello(string, int)。このため、依存関係の実装を気にすることなくhello(string, int)の機能をテストするために、呼び出しとその戻りを模擬しています。

上記を実際のクラス名で囲み、クラスMyProgramをモックしてGetLastName()の新しい実装(モック)を提供していることを明確に示します

答えてくれてありがとう。別のメソッドを呼び出す別のメソッドを呼び出すメソッドをテストしたい場合はどうなりますか?たとえばメソッドhelloが別のメソッドを呼び出した場合はどうなりますか?

ユニットテストを構築する場合も同じ原則が当てはまります(unitテストであると仮定すると、統合テストなどではなく、常にテストに集中したいoneパブリックメソッド- 単体テストと統合テストの違いは何ですか?

public class Foo
{

    public string Bar()
    {
        return string.Format("{0}Bar", Baz(5));;
    }

    public virtual string Baz(int someNumber)
    {
        return string.Format("{0}Baz", DoStuff(someNumber).ToString());
    }

    public virtual int DoStuff(int someNumber)
    {
        return someNumber+1;
    }

}

ユニットテストBar()の場合、Baz(int)の実装、またはさらに悪いDoStuff(int)の実装については気にしません。注私たちは実装について気にしません、私たちdo値を返すことに注意してください。 Bar()から見ると、重要なのはBaz(int)が文字列を返すことだけです。何の糸? Bar()の単体テストは関係ありません。

Bar()のサンプルテスト:

[TestMethod]
public void Bar_ReturnsBazValueWithBarAppended
{
    // Arrange
    string testBazReturn = "test";
    Mock<Foo> mock = new Mock<Foo>();
    mock.CallBase = true;
    mock
        .Setup(s => s.Baz(It.IsAny<int>())
        .Returns(testBazReturn);

    // Act
    var results = mock.Object.Bar();

    // Assert
    Assert.AreEqual(string.Format("{0}{1}", testBazReturn, "Bar"), results);
    mock.Verify(v => v.Baz(It.IsAny<int>())); // Verifies that Baz was called
}

上記では、Baz(int)DoStuff(int)の実際の実装は無視しているため、Baz(int)DoStuff(int)の実際の実装は重要ではありません。プレイすることすらありません。

ここで、Baz(int)をテストする場合、同じ考え方に従います。

[TestMethod]
public void Baz_ReturnsDoStuffValueWithBazAppended
{
    // Arrange
    int testDoStuffReturn = 1;
    Mock<Foo> mock = new Mock<Foo>();
    mock.CallBase = true;
    mock
        .Setup(s => s.DoStuff(It.IsAny<int>())
        .Returns(testDoStuffReturn);

    // Act
    var results = mock.Object.Baz(5);

    // Assert
    Assert.AreEqual(string.Format("{0}{1}", results, "Baz"), results); // Validates the result
    mock.Verify(v => v.DoStuff(It.IsAny<int>())); // Verifies that DoStuff was called
}

上記では、Baz(int)の単体テストを行っているため、Bar()は関係ありません。DoStuff(int)で関係する唯一のことは、値(howではなく、その値に到達します。)

そして最後にDoStuff(int)

[TestMethod]
public void DoStuff_ReturnsParameterPlusOne()
{
    // Arrange
    Foo foo = new Foo();
    int passed = 1;
    int expected = passed + 1;

    // Act
    var results = foo.DoStuff(passed);

    // Assert
    Assert.AreEqual(expected, results);
}
9
Kritner