c# - 单元测试基类和派生类
问题描述
所以我有2节课。ItemWithAttributes
和ItemWithNameAndAttributes
(从 1 派生)。
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
我将有更多相同的测试并重新测试基类。我觉得我的小班很快就变得非常复杂。
解决方案
根据示例代码,我没有看到通过继承进行整合的好方法。测试确实遵循几乎相同的结构(实例化一个对象,对那个对象做一些事情,验证结果——即,安排,行动,断言),但实现细节是有意义的不同(“行动”步骤是相同的,但构造函数和预期结果不同)。在这种情况下,测试和断言框架已经完成了尽可能多的重复数据删除。
注意:使用一些单元测试框架(我主要使用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);
}
}
在编写该示例时,我注意到--testing隐式测试Verify_AttributesToParenthesesString
有点多余。如果存在只是为了支持,那么它是一个实现细节。可以通过删除和更改对.Verify_ToString
ToString
AttributesToParenthesesString
AttributesToParenthesesString
ToString
Verify_AttributesToParenthesesString
AttributesToParenthesesString
protected
推荐阅读
- android - 为什么离子响应作为地理定位错误允许?
- r-markdown - Rmarkdown:PDF文件无法循环生成
- swift4 - Dispatchqueue 后台线程更新在 iOS 12 上不起作用
- ios - iOS UIImagePickerController 显示空白页
- java - 如何在 Linux 服务器上的 shellscript 中提供密码?
- python - 合并两个没有重复值的列表
- sql-server - 在 sql 过程中返回空或 null
- c++ - C++中的算术运算符重载
- c# - 时间:2019-05-10 标签:c#windowsshudownprocess怪异
- bash - 如何通过循环遍历 TSV 将选项分配给下标?