繁体   English   中英

单元测试基类和派生类

[英]Unit testing base and derived class

所以我有2节课。 ItemWithAttributesItemWithNameAndAttributes (源自 1st)。

using System;
using System.Collections.Generic;
using System.Linq;
using Helpers;

namespace Objects.Base
{
    public class ItemWithAttributes
    {
        public IEnumerable<string> Attributes { get; }

        public ItemWithAttributes(IEnumerable<string> attributes)
        {
            if (attributes == null)
                throw new ArgumentNullException(nameof(attributes), "Parameter can not be mull.");

            Attributes = attributes.ToArray();
        }

        public virtual string AttributesToParenthesesString(bool prependSpace)
        {
            return $"{Attributes.ToParenthesesString(prependSpace)}";
        }

        public override string ToString()
        {
            return AttributesToParenthesesString(false);
        }
    }
}
using System;
using System.Collections.Generic;

namespace Objects.Base
{
    public class ItemWithNameAndAttributes : ItemWithAttributes
    {
        public string Name { get; }

        public ItemWithNameAndAttributes(string name, IEnumerable<string> attributes) : base(attributes)
        {
            if (name == null)
                throw new ArgumentNullException(nameof(name), "Parameter can not be null.");

            if (name.Length == 0)
                throw new ArgumentException("Parameter can not be empty.", nameof(name));

            Name = name;
        }

        public override string ToString()
        {
            return $"{Name}{AttributesToParenthesesString(true)}";
        }
    }
}

我想进入单元测试,所以这就是我到目前为止为我的两个班级所做的。 我阅读了一些关于测试方法命名的命名约定,但我现在感觉有点卡住了。

using System;
using System.Collections.Generic;
using System.Linq;
using Objects.Base;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTests.Objects.Base
{
    [TestClass]
    public class ItemWithAttributesTests
    {
        [TestMethod]
        public void Constructor_AttributesWithElements_PropertyEqualToInput()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            CollectionAssert.AreEqual(attributes, itemWithAttributes.Attributes.ToList());
        }

        [TestMethod]
        public void Constructor_AttributesWithoutElements_PropertyEqualToInput()
        {
            var attributes = new List<string>() { };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            CollectionAssert.AreEqual(attributes, itemWithAttributes.Attributes.ToList());
        }

        [TestMethod]
        public void Constructor_AttributesNull_ThrowArgumentNullException()
        {
            Assert.ThrowsException<ArgumentNullException>(() => new ItemWithAttributes(null));
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithElementsAndPrependFalse_ReturnsEqualString()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.AttributesToParenthesesString(false);

            Assert.AreEqual("(Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithElementsAndPrependTrue_ReturnsEqualString()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.AttributesToParenthesesString(true);

            Assert.AreEqual(" (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithoutElementsAndPrependFalse_ReturnsEqualString()
        {
            var attributes = new List<string>() {  };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.AttributesToParenthesesString(false);

            Assert.AreEqual("", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithoutElementsAndPrependTrue_ReturnsEqualString()
        {
            var attributes = new List<string>() {  };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.AttributesToParenthesesString(true);

            Assert.AreEqual("", result);
        }

        [TestMethod]
        public void ToString_AttributesWithElements_ReturnsEqualString()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.ToString();

            Assert.AreEqual("(Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void ToString_AttributesWithoutElements_ReturnsEqualString()
        {
            var attributes = new List<string>() { };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.ToString();

            Assert.AreEqual("", result);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using Objects.Base;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTests.Objects.Base
{
    [TestClass]
    public class ItemWithNameAndAttributesTests
    {
        [TestMethod]
        public void Constructor_NameAndAttributesWithElements_PropertiesAreEqualToInput()
        {
            var name = "Name";
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            Assert.AreEqual(name, itemWithNameAndAttributes.Name);
            CollectionAssert.AreEqual(attributes, itemWithNameAndAttributes.Attributes.ToList());
        }

        [TestMethod]
        public void Constructor_NameAndAttributesWithoutElements_PropertiesAreEqualToInput()
        {
            var name = "Name";
            var attributes = new List<string>() { };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            Assert.AreEqual(name, itemWithNameAndAttributes.Name);
            CollectionAssert.AreEqual(attributes, itemWithNameAndAttributes.Attributes.ToList());
        }


        [TestMethod]
        public void Constructor_NameEmpty_ThrowArgumentException()
        {
            var name = string.Empty;
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            Assert.ThrowsException<ArgumentException>(() => new ItemWithNameAndAttributes(name, attributes));
        }

        [TestMethod]
        public void Constructor_NameNull_ThrowArgumentNullException()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            Assert.ThrowsException<ArgumentNullException>(() => new ItemWithNameAndAttributes(null, attributes));
        }

        [TestMethod]
        public void Constructor_AttributesNull_ThrowArgumentNullException()
        {
            var name = "Name";
            Assert.ThrowsException<ArgumentNullException>(() => new ItemWithNameAndAttributes(name, null));
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithElementsAndPrependFalse_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.AttributesToParenthesesString(false);

            Assert.AreEqual("(Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithElementsAndPrependTrue_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.AttributesToParenthesesString(true);

            Assert.AreEqual(" (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithoutElementsAndPrependFalse_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.AttributesToParenthesesString(false);

            Assert.AreEqual("", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithoutElementsAndPrependTrue_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.AttributesToParenthesesString(true);

            Assert.AreEqual("", result);
        }

        [TestMethod]
        public void ToString_AttributesArgumentIsListWithElements_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.ToString();

            Assert.AreEqual("Name (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void ToString_AttributesArgumentIsListWithoutElements_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.ToString();

            Assert.AreEqual("Name", result);
        }
    }
}

我注意到我的派生类ItemWithNameAndAttributes的单元测试与我的基类ItemWithAttributes的单元测试几乎相同,但只是多一点和不同,因为我还需要验证 name 参数。 我不确定这是否是正确的方法,或者是否有某种方法可以在派生类中重用基类中的测试。 如果我保持这种当前模式,当我从ItemWithNameAndAttributes派生时,我将有更多相同的测试并重新测试基类。 我觉得对于我的小班级来说,它很快变得非常复杂。

根据示例代码,我没有看到通过继承进行整合的好方法。 测试确实遵循几乎相同的结构(实例化一个对象,对该对象做一些事情,验证结果——即,Arrange、Act、Assert),但实现细节是有意义的不同(“act”步骤是相同的,但构造函数和预期结果不同)。 在这种情况下,测试和断言框架已经完成了尽可能多的重复数据删除。

注意:使用某些单元测试框架(我主要使用xUnit.net ),可以创建单元测试的继承层次结构,其中所有基本夹具的测试作为每个继承夹具的一部分运行,但我认为不是对示例问题有帮助。 是描述继承测试的另一个答案。

如果您愿意使用 xUnit 作为您的测试框架,您可以使用“理论”来整合一些测试:

public class ItemWithNameAndAttributesTests_Theories
{
    [Theory]
    [InlineData("Name", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" })]
    [InlineData("Name", new string[0])]
    public void Verify_Constructor_PropertiesAreEqualToInput(string name, string[] attributes)
    {
        var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, new List<string>(attributes));

        Assert.Equal(name, itemWithNameAndAttributes.Name);
        Assert.Equal(attributes, itemWithNameAndAttributes.Attributes);
    }

    [Theory]
    [InlineData("", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, typeof(ArgumentException))]
    [InlineData(null, new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, typeof(ArgumentNullException))]
    [InlineData("Name", null, typeof(ArgumentNullException))]
    public void Verify_Constructor_ThrowException(string name, string[] attributes, Type exceptionType)
    {
        Assert.Throws(exceptionType, () => new ItemWithNameAndAttributes(name, attributes));
    }

    [Theory]
    [InlineData("Name", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, false, "(Item 1) (Item 2) (Item 3) (Item 4) (Item 5)")]
    [InlineData("Name", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, true, " (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)")]
    [InlineData("Name", new string[0], false, "")]
    [InlineData("Name", new string[0], true, "")]
    public void Verify_AttributesToParenthesesString(string name, string[] attributes, bool prependSpace, string expected)
    {
        var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

        var result = itemWithNameAndAttributes.AttributesToParenthesesString(prependSpace);

        Assert.Equal(expected, result);
    }

    [Theory]
    [InlineData("Name", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, "Name (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)")]
    [InlineData("Name", new string[0], "Name")]
    public void Verify_ToString(string name, string[] attributes, string expected)
    {
        var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

        var result = itemWithNameAndAttributes.ToString();

        Assert.Equal(expected, result);
    }
}

在编写该示例时,我注意到Verify_AttributesToParenthesesStringVerify_ToString --testing ToString隐式测试AttributesToParenthesesString有点多余。 如果AttributesToParenthesesString存在只是为了支持ToString ,那么它是一个实现细节。 可以通过删除Verify_AttributesToParenthesesString并将AttributesToParenthesesString的访问权限更改为protected来简化代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM