簡體   English   中英

如何在C#中使用NUnit編寫存根方法

[英]How write stub method with NUnit in C#

我有2節課:

  • FirstDeep.cs
  • SecondDeep.cs

    我做了簡單的代碼,例如:


class FirstDeep
    {
        public FirstDeep() { }

        public string AddA(string str)
        {
            SecondDeep sd = new SecondDeep();
            bool flag = sd.SomethingToDo(str);

            if (flag == true)
                str = string.Concat(str, "AAA");
            else
                str = string.Concat(str, "BBB");

            return str;
        }
    }

class SecondDeep
    {
        public bool SomethingToDo(string str)
        {
            bool flag = false;
            if (str.Length < 10)
            {
                //todo something in DB, and after that flag should be TRUE
            }
            return flag;
        }
    }

然后,我想為方法“ AddA”編寫單元測試:

class Tests
    {
        [Test]
        public void AddATest()
        {
            string expected = "ABCAAA";

            FirstDeep fd = new FirstDeep();
            string res = fd.AddA("ABC");

            Assert.AreEqual(expected, res);
        }
    }

之后,我遇到了麻煩,我不知道在Test類中為方法SomethingToDo編寫正確的存根。 我總是有假的。 我應該返回TRUE。 但是如何?

允許您編寫存根的一個好方法是使用依賴注入 FirstDeep取決於SecondDeep ,在測試中,您想用存根替換SecondDeep

首先通過提取用於SecondDeep的接口來更改現有代碼,然后將其注入構造函數中的FirstDeep中:

interface ISecondDeep {

  Boolean SomethingToDo(String str);

}

class SecondDeep : ISecondDeep { ... }

class FirstDeep {

  readonly ISecondDeep secondDeep;

  public FirstDeep(ISecondDeep secondDeep) {
    this.secondDeep = secondDeep;
  }

  public String AddA(String str) {   
    var flag = this.secondDeep.SomethingToDo(str);
    ...
  }

}

請注意, FirstDeep不再創建SecondDeep實例。 而是將一個實例注入構造函數中。

在測試中,您可以為ISecondDeep創建存根,其中SomethingToDo始終返回true:

class SecondDeepStub : ISecondDeep {

  public Boolean SomethingToDo(String str) {
    return true;
  }

}

在測試中,您使用存根:

var firstDeep = new FirstDeep(new SecondDeepStub());

在生產代碼中,使用“真實的” SecondDeep

var firstDeep = new FirstDeep(new SecondDeep());

使用依賴項注入容器和存根框架可以使很多操作變得更容易。

如果您不想重寫代碼,則可以使用諸如Microsoft Moles之類的框架來攔截調用。 在Visual Studio的下一版本中,類似的技術將在Fakes Framework中可用。

為了使您的代碼可測試,請不要在類內部實例化依賴關系。 使用依賴注入 (通過構造函數,屬性或參數)。 還可以使用抽象類或接口來模擬依賴項:

class FirstDeep
{
    private ISecondDeep oa;

    public FirstDeep(ISecondDeep oa) 
    { 
        this.oa = oa;
    }

    public string AddA(string str)
    {
       return String.Concat(str, oa.SomethingToDo(str) ? "AAA" : "BBB");
    }
}

依賴於抽象允許您隔離測試類。

interface ISecondDeep
{
   bool SomethingToDo(string str);
}

class SecondDeep : ISecondDeep
{
    public bool SomethingToDo(string str)
    {
       bool flag = false;
       if (str.Length < 10)
       {
           // without abstraction your test will require database
       }
       return flag;
    }
}

這是測試樣本(使用Moq )。 它顯示了如何從調用返回true到模擬的依賴項:

[TestFixture]
class Tests
{
    [Test]
    public void AddAAATest()
    {
        // Arrange
        Mock<ISecondDeep> secondDeep = new Mock<ISecondDeep>();
        secondDeep.Setup(x => x.SomethingToDo(It.IsAny<string>())).Returns(true);
        // Act
        FirstDeep fd = new FirstDeep(secondDeep.Object);
        // Assert
        Assert.That(fd.AddA("ABD"), Is.EqualTo("ABCAAA"));
     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM