簡體   English   中英

與私有集合相關的單元測試公共方法

[英]Unit Test public methods related to a private collection

我的班級有一個私人的惰性字典和一些與之互動的方法,像這樣

public class MyClass : IExampleClass
{
    private Lazy<Dictionary<string, IMyObject>> myObjects = new Lazy<Dictionary<string, IMyObject>>();
    private Dictionary<string, IMyObject> MyObjects
    {
        get
        {
            return myObjects.Value;
        }
    }

    public class MyClass()
    {}

    public void RegisterObject(string name, IMyObject object)
    {
        logger.LogInfo("Executed RegisterObject etc.");

        if (String.IsNullOrEmpty(name) == false && object != null && MyObjects.ContainsKey(name) == false)
        {
             MyObjects.Add(name, object);
        }
        else
        {
             logger.LogWarning("Cannot register the object because etc.");
        }
    }

    public IMyObject GetObject(string name)
    {
        logger.LogInfo("Executed GetObject etc.");

        IMyObject obj = null;
        if (String.IsNullOrEmpty(name) == false)
        {
            Objects.TryGetValue(name, out obj);
        }

        return obj;
    }
}

這很有用,因為有時會發生某些插入的對象為null的情況,因此我避免了進一步的損壞,避免添加它們。 現在我在測試階段遇到了一個問題(我知道,對我感到羞恥,我在測試之前編寫了代碼),因為我被迫在同一測試中使用這兩種方法:

[TestFixture]
public class MyClassTest 
{
    [Test]
    public void RegisterObject_WithNullNameAndNullObject_DoNothing()
    {
        //Arrange
        string inputName = null;
        IMyObject inputObject = null;
        IExampleClass sut = new MyClass();

        //Act
        sut.RegisterObject(inputName, inputObject);

        //Assert
        IMyObject actualValue = sut.GetObject(inputName);
        Assert.IsNull(actualValue);
    }

    ...
}

最重要的是,我該如何處理要在字典中插入一個元素的測試?

    [Test]
    public void RegisterObject_AlreadyInserted_DoNothing()
    {
        //Arrange
        string inputName = "test";
        IMyObject inputObject = A.Dummy<IMyObject>();
        IExampleClass sut = new MyClass();

        // ??? 
        sut.RegisterObject(inputName, inputObject);
        // how can i effectively test the method if i'm using it more than once???

        //Act
        sut.RegisterObject(inputName, inputObject);

        //Assert
        IMyObject actualValue = sut.GetObject(inputName);

        // ???
        Assert.AreEqual(inputObject, actualValue);
        // What i've tested here? The fact that the dictionary contains
        // the object doesn't mean that the second call of RegisterObject
        // is ignored.
    }

所以最后我問:

  1. 測試RegisterObject在其中調用GetObject是否正確?
  2. 如果必須測試第二次插入被忽略,該如何安排字典?

附帶說明一下,我對RegisterObject有7個單獨的測試:

  • RegisterObject_WithNullNameAndNullObject_DoNothing()
  • RegisterObject_WithNullNameAndValidObject_DoNothing()
  • RegisterObject_WithEmptyNameAndNullObject_DoNothing()
  • RegisterObject_WithEmptyNameAndValidObject_DoNothing()
  • RegisterObject_WithValidNameAndNullObject_DoNothing()
  • RegisterObject_WithValidNameAndValidObject_RegisterObject()
  • RegisterObject_AlreadyInserted_DoNothing()

太過分了嗎? 這個簡單行為的測試太多了嗎?

測試RegisterObject在其中調用GetObject是否正確?

鑒於我們對MyClass的公共接口所了解的只是它具有RegisterObjectGetObject ,所以我認為您還不能做其他任何事情。 即使您可以做其他事情,我也不會。 您要確保該類對其使用者具有某種特定的行為,因此請像使用者一樣使用它。 這樣您就可以判斷它是否在工作。

如果必須測試第二次插入被忽略,該如何安排字典?

從消費者的角度考慮這一點。 你想發生什么? 似乎您想表明,如果在現有鍵下插入第二個對象,則該方法將以靜默方式成功執行,但是存儲的值是原始值。 我們如何知道存儲了什么? 通過調用GetObject 因此,我認為您進行的測試很好,但是我將使用其他值來插入。 這樣,您可以判斷是否有任何更改。 如果GetObject返回原始值,則您的方法做對了。

暫無
暫無

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

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