如何在c#中测试setter?

问题描述 投票:0回答:1

我正在开始使用c#,我被要求做一个任务,包含编写一个setter的单元测试和检查它的输出。我被要求做一个任务,包含编写一个setter的单元测试并检查其输出。我不明白为什么要测试一些不包含任何逻辑的琐碎的东西,这里有一个例子(SetKeywords()是要测试的方法)。

public struct Keyword
{
    private string keyword;
    private KeywordTypes type;

    public Keyword(string keyword, KeywordTypes Type = 
    KeywordTypes.String)
    {
        this.keyword = keyword;
        this.type = Type;  
    }

    public string GetString()
    {
        return this.keyword;
    }

    public KeywordTypes WhichType()
    {
        return this.type;
    }
}

public class ShopParser
{
    private Keyword[] keywords = new Keyword[0];

    public void **SetKeywords**(Keyword[] tags)
    {
        keywords = tags;
    }
}
    public Keyword[] GetKeywords()
    {
            return this.keywords;
    } 
    public static KeywordPair[] ExtractFromTaG(ShopParser parser, string 
    serializedInput)
    {
            var findings = new KeywordPair[0];
            foreach (var keyword in parser.GetKeywords())
            {
                var start = serializedInput.IndexOf(keyword.GetStart());

                // Check if keyword is in input string, if not continue 
                with next keyword.

                if (start <= -1) continue;

                var end = serializedInput.LastIndexOf(keyword.GetEnd());

                // Extract the thing between the tags. Tag excluded
                start += keyword.GetStart().Length;

                var substring = serializedInput.Substring(start, end - 
                start);

                // Add substring to result list

                var tmp = new KeywordPair[findings.Length + 1];
                var i = 0;
                for (; i < findings.Length; ++i)
                {
                    tmp[i] = findings[i];
                }
                tmp[i] = new KeywordPair(keyword, substring);
                findings = tmp;
            }
            return findings;
    }

}
c# .net unit-testing nunit setter
1个回答
0
投票

如何测试?

当你调用 SetKeywords它应该做一些事情。现在,它设置了内部数组 keywords. 所以,你需要问自己的问题是,你怎么能确定它做到了这一点?那么你有一个 GetKeywords 方法返回内部数组,所以我们可以用它来进行测试,如下图。

[TestClass]
public class ShopParserTests
{
    [TestMethod]
    public void SetKeyWords__WhenGivenAnArray__MustSetTheInternalArray()
    {
        // Arrange
        var k1 = new Keyword("One", KeywordTypes.String);
        var k2 = new Keyword("Two");
        var parser = new ShopParser();
        var keys = new Keyword[] { k1, k2 };

        // Act
        parser.SetKeywords(keys);

        // Assert
        Keyword[] keysReturned = parser.GetKeywords();
        Assert.AreEqual(keysReturned[0].GetString(), k1.GetString());
        Assert.AreEqual(keysReturned[0].WhichType(), k1.WhichType());
        Assert.AreEqual(keysReturned[1].GetString(), k2.GetString());
        Assert.AreEqual(keysReturned[1].WhichType(), k2.WhichType());

        // More tests
    }
}

一些建议

请记住,你可能需要根据你的需求编写更多的测试。例如,如果用户这样做了怎么办。

Keyword[] keysReturned = parser.GetKeywords();
keys[0] = new Keyword();

你想允许这样做吗?

另外,在C#中,你的类可以被简化并利用属性。所以你的 Keyword 和ShopParser类要这样写。

public struct Keyword
{
    public Keyword(string keyword, KeywordTypes type =
    KeywordTypes.String)
    {
        this.TheKeyword = keyword;
        this.KeyType= type;
    }

    public string TheKeyword { get; private set; }
    public KeywordTypes KeyType { get; private set; }
}

public class ShopParser
{
    public void SetKeywords(Keyword[] tags)
    {
        this.KeyWords = tags;
    }

    public Keyword[] KeyWords { get; private set; }
}

2
投票

缺乏复杂的代码并不意味着该类的作者没有任何设计上的决定,这些决定应该通过单元测试来验证和保护。例如,你为集合中的项目选择了值类型,这使得一些行为不可能实现,而一些行为则是微不足道的--测试的目的是为了澄清这个类实现了那个 设计决定 适当并保护 行径 类的单元测试,以备将来修改。

为集合类型的属性设置器进行单元测试(与值类型不同的是,集合类型的属性设置器是一个单元测试。int)实际上是 非同小可 因为我们必须验证类的契约是否被定义并得到正确的支持--setter是对一个集合进行复制还是引用现有的集合,它是进行深复制还是浅复制?正确地测试每一种情况绝对不是一项琐碎的任务。(同样在较小的程度上适用于所有引用类型的属性,但在非集合的情况下,对行为的期望通常与默认值更一致)。

所以你要做的是 之前 编写测试是为了决定你的集合属性的行为--它是在设置时进行复制还是引用原始的实时实例。如果集合是引用类型的(问题中不是这种情况),你还需要决定它是进行浅层复制还是深层复制(深层复制是不寻常的)。

在你做出决定后,写测试来验证就有点小题大做了。你添加以下测试。

  • 通过getter暴露的集合是否与调用setter的集合顺序相同(适用于复制和引用两种方法)。
  • 在集合中使用setter并修改原始集合(在数组的情况下改变集合中的项目)。验证由getter暴露的集合是否正确(要么与更新的集合相匹配,要么与复制的集合保持不变)。
  • 如果使用非不可更改的引用类型集合,则验证修改单个项目的行为是否符合预期(要么反映出对非深层拷贝的修改,要么保持不变)。
  • 如果集合只是指原来的一个测试 缩短为只检查原始值和getter返回的值之间的引用是否相等,但这样做不会导致 文件 的行为,并限制了将来修改的能力。

我们可能需要额外的测试来验证作为getter结果返回的集合是否按照类作者的设计行为--特别是对结果集合的修改是否反映在类的状态中(getter返回状态的浅层拷贝或直接暴露内部状态,如问题所示)。

请注意,不鼓励为集合属性设置器--请参见 CA2227:集合属性应只读。. 所以问题中的代码有点遵循建议,但更好的名称,如 "AddKeywords""ReplaceKeywords "将澄清行为,而不是一般的 "设置"。

© www.soinside.com 2019 - 2024. All rights reserved.