在 MSTest 方法参数中传递对象
Passing object in MSTest method parameters
我正在 ASP.NET 开发一款战舰游戏,但我在使用 MSTest 进行单元测试时遇到了问题。
我想测试每种类型的船的创建并验证每艘船的构造函数是否制造出具有良好宽度的所需船等。因此,我决定编写一个带有标签 [DataTestMethod] 的通用方法。但是我不明白如何使用对象作为参数。
这是我想要的示例:
[DataTestMethod]
[DataRow("Aircraft Cruiser", 5, OccupationType.Aircraft, new Aircraft())]
public void CreateAircraft(string description, int width, OccupationType occupationType, Ship resultShip)
{
var expectedShip = new Ship
{
Description = description,
Width = width,
OccupationType = occupationType
};
Assert.AreEqual(expectedShip, resultShip)
}
但它显然不起作用。所以我做了类似的事情:
[DataTestMethod]
[DataRow("Aircraft Cruiser", 5, OccupationType.Aircraft, "Aircraft")]
public void CreateAircraft(string description, int width, OccupationType occupationType, string shipType)
{
var expectedShip = new Ship
{
Description = description,
Width = width,
OccupationType = occupationType
};
Ship resultShip = null;
switch (shipType)
{
case "Aircraft":
resultShip = new Aircraft();
break;
}
Assert.AreEqual(expectedShip, resultShip);
}
但我确信这不是实现我想要的最有效方法。你有什么想法吗?
非常感谢。
您正在比较引用类型,这在您比较内存中的引用时不起作用,它们不相等。您应该覆盖 Equals() 函数,然后在您的测试中使用它。
Equals 函数接受一个类型,然后您只需进行比较,例如,将其添加到您的 Ship class:
public override bool Equals(Ship obj)
{
if (this.Width != obj.Width)
{
return false;
}
return true;
}
那么您只需在测试中执行此操作即可:
Assert.IsTrue(expectedShip.Equals(resultShip))
第一个示例根本无法在 C# 中完成。根据规范,属性必须在其 constructor/properties 中采用常量参数,并且禁止任何其他参数(因为属性是在编译时在二进制文件中烘焙的)。在这种情况下,导致它失败的原因是属性中的构造函数调用 new Aircraft()
,这是一个非常量表达式(它导致 Aircraft
class 的构造函数变为 运行), 所以它根本不能用在属性中。
作为解决方法,字符串通常是一个不错的选择。请注意,C#6 引入了 nameof
运算符来缓解这种情况并提供一些编译器支持,如下所示:
[DataRow("Aircraft Cruiser", 5, OccupationType.Aircraft, nameof(Aircraft))]
至于方法代码本身,如果您事先知道所有可能性,switch
是一个选项,否则您需要涉及反射以从 class 名称创建对象。
您可以使用 DynamicData
属性将对象传递给 MS 测试方法。这指定了一个将生成测试数据的静态方法。
这在您的测试方法中使用如下:
[TestMethod]
[DynamicData(nameof(GetTestData), DynamicDataSourceType.Method)]
public void CreateAircraft(string description, int width,
OccupationType occupationType, Ship resultShip)
return测试数据的方法return是对象[]的IEnumerable,可以像这样实现:
private static IEnumerable<object[]> GetTestData()
{
yield return new object[]
{
"Aircraft Cruiser",
5,
OccupationType.Aircraft,
new Aircraft()
};
yield return new object[]
{
"X-Wing",
6,
OccupationType.StarFighter,
new Aircraft()
};
}
我正在 ASP.NET 开发一款战舰游戏,但我在使用 MSTest 进行单元测试时遇到了问题。
我想测试每种类型的船的创建并验证每艘船的构造函数是否制造出具有良好宽度的所需船等。因此,我决定编写一个带有标签 [DataTestMethod] 的通用方法。但是我不明白如何使用对象作为参数。
这是我想要的示例:
[DataTestMethod]
[DataRow("Aircraft Cruiser", 5, OccupationType.Aircraft, new Aircraft())]
public void CreateAircraft(string description, int width, OccupationType occupationType, Ship resultShip)
{
var expectedShip = new Ship
{
Description = description,
Width = width,
OccupationType = occupationType
};
Assert.AreEqual(expectedShip, resultShip)
}
但它显然不起作用。所以我做了类似的事情:
[DataTestMethod]
[DataRow("Aircraft Cruiser", 5, OccupationType.Aircraft, "Aircraft")]
public void CreateAircraft(string description, int width, OccupationType occupationType, string shipType)
{
var expectedShip = new Ship
{
Description = description,
Width = width,
OccupationType = occupationType
};
Ship resultShip = null;
switch (shipType)
{
case "Aircraft":
resultShip = new Aircraft();
break;
}
Assert.AreEqual(expectedShip, resultShip);
}
但我确信这不是实现我想要的最有效方法。你有什么想法吗?
非常感谢。
您正在比较引用类型,这在您比较内存中的引用时不起作用,它们不相等。您应该覆盖 Equals() 函数,然后在您的测试中使用它。
Equals 函数接受一个类型,然后您只需进行比较,例如,将其添加到您的 Ship class:
public override bool Equals(Ship obj)
{
if (this.Width != obj.Width)
{
return false;
}
return true;
}
那么您只需在测试中执行此操作即可:
Assert.IsTrue(expectedShip.Equals(resultShip))
第一个示例根本无法在 C# 中完成。根据规范,属性必须在其 constructor/properties 中采用常量参数,并且禁止任何其他参数(因为属性是在编译时在二进制文件中烘焙的)。在这种情况下,导致它失败的原因是属性中的构造函数调用 new Aircraft()
,这是一个非常量表达式(它导致 Aircraft
class 的构造函数变为 运行), 所以它根本不能用在属性中。
作为解决方法,字符串通常是一个不错的选择。请注意,C#6 引入了 nameof
运算符来缓解这种情况并提供一些编译器支持,如下所示:
[DataRow("Aircraft Cruiser", 5, OccupationType.Aircraft, nameof(Aircraft))]
至于方法代码本身,如果您事先知道所有可能性,switch
是一个选项,否则您需要涉及反射以从 class 名称创建对象。
您可以使用 DynamicData
属性将对象传递给 MS 测试方法。这指定了一个将生成测试数据的静态方法。
这在您的测试方法中使用如下:
[TestMethod]
[DynamicData(nameof(GetTestData), DynamicDataSourceType.Method)]
public void CreateAircraft(string description, int width,
OccupationType occupationType, Ship resultShip)
return测试数据的方法return是对象[]的IEnumerable,可以像这样实现:
private static IEnumerable<object[]> GetTestData()
{
yield return new object[]
{
"Aircraft Cruiser",
5,
OccupationType.Aircraft,
new Aircraft()
};
yield return new object[]
{
"X-Wing",
6,
OccupationType.StarFighter,
new Aircraft()
};
}