[英]How to test culture-deendent and culture-independent ToString methods?
我必须用换句话说写我的问题。
由于某些原因,我正在开发自己的几何原始结构:点和大小:
public struct Point : IEquatable<Point> {
public static bool operator ==(Point left, Point right) {
return left.Equals(right);
}
public static bool operator !=(Point left, Point right) {
return !left.Equals(right);
}
public static implicit operator Point(System.Drawing.Point point) {
return new Point(point.X, point.Y);
}
int x;
int y;
public int X { get { return x; } set { x = value; } }
public int Y { get { return y; } set { y = value; } }
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public bool Equals(Point other) {
return
x == other.x &&
y == other.y;
}
public override bool Equals(object obj) {
if (obj.GetType() != typeof(Point))
return false;
return Equals((Point)obj);
}
public override int GetHashCode() {
return x^y;
}
public override string ToString() {
return $"{{X={x.ToString(CultureInfo.CurrentCulture)}, Y={y.ToString(CultureInfo.CurrentCulture)}}}";
}
public string ToStringInvariant() {
return $"{{X={x.ToString(CultureInfo.InvariantCulture)}, Y={y.ToString(CultureInfo.InvariantCulture)}}}";
}
}
public struct Size : IEquatable<Size> {
public static bool operator ==(Size size1, Size size2) {
return size1.Equals(size2);
}
public static bool operator !=(Size size1, Size size2) {
return !size1.Equals(size2);
}
public static implicit operator Size(System.Drawing.Size size) {
return new Size(size.Width, size.Height);
}
int width;
int height;
public int Width {
get { return width; }
set {
if (value < 0)
throw new ArgumentException("The Width property value must not be negative.");
width = value;
}
}
public int Height {
get { return height; }
set {
if (value < 0)
throw new ArgumentException("The Height property value must not be negative.");
height = value;
}
}
public Size(int width, int height) {
if (width < 0 || height < 0)
throw new ArgumentException("The Width and Height property values must not be negative.");
this.width = width;
this.height = height;
}
public bool Equals(Size other) {
return
width == other.width &&
height == other.height;
}
public override bool Equals(object obj) {
if (obj.GetType() != typeof(Size))
return false;
return Equals((Size)obj);
}
public override int GetHashCode() {
return HashCodeHelper.CalculateGeneric(width, height);
}
public override string ToString() {
return $"{{Width={width.ToString(CultureInfo.CurrentCulture)}, Height={height.ToString(CultureInfo.CurrentCulture)}}}";
}
public string ToStringInvariant() {
return $"{{Width={width.ToString(CultureInfo.InvariantCulture)}, Height={height.ToString(CultureInfo.InvariantCulture)}}}";
}
}
现在我需要编写测试,特别是我应该测试我的 ToString 和 ToStringInvariant() 方法。
为此,我需要一些文化,其中整数格式不同于 InvariantCulture 整数格式。
由于 Point 类可以有负数,我可以更改负号表示并编写测试:
[Test]
public void ToStringTest() {
Point point = new Point(-1, 2);
var preCulture = Thread.CurrentThread.CurrentCulture;
try {
var enCulture = new CultureInfo("en-US");
enCulture.NumberFormat.NegativeSign = "Minus!";
Thread.CurrentThread.CurrentCulture = enCulture;
Assert.That(point.ToString() == "{X=Minus!1, Y=2}");
}
finally {
Thread.CurrentThread.CurrentCulture = preCulture;
}
}
[Test]
public void ToStringInvariantTest() {
Point point = new Point(1, 2);
var preCulture = Thread.CurrentThread.CurrentCulture;
try {
var enCulture = new CultureInfo("en-US");
enCulture.NumberFormat.NegativeSign = "Minus!";
Thread.CurrentThread.CurrentCulture = enCulture;
Assert.That(point.ToStringInvariant() == "{X=1, Y=2}");
}
finally {
Thread.CurrentThread.CurrentCulture = preCulture;
}
}
Size 结构只能有正或零字段,所以我应该更改数字表示。 我尝试使用“prs-AF”文化。 但是 1.ToString("prs-AF") 仍然是“1”。 如何测试 Size 结构的 ToString 和 ToStringInvariant 方法?
旧文本:
我有原语:Point 和 Size 类。 我以这种方式覆盖 ToString 方法:
public override string ToString() {
return $"{{X={x.ToString(CultureInfo.CurrentCulture)}, Y={y.ToString(CultureInfo.CurrentCulture)}}}";
}
我也有一个
public string ToStringInvariant() {
return $"{{X={x.ToString(CultureInfo.InvariantCulture)}, Y={y.ToString(CultureInfo.InvariantCulture)}}}";
}
我需要对这种方法进行测试。 对于 Point 类,我可以在 CultureInfo 实例中设置 NegativeSign:
[Test]
public void ToStringTest() {
Point point = new Point(-1, 2);
var preCulture = Thread.CurrentThread.CurrentCulture;
try {
var enCulture = new CultureInfo("en-US");
enCulture.NumberFormat.NegativeSign = "Minus!";
Thread.CurrentThread.CurrentCulture = enCulture;
Assert.That(point.ToString() == "{X=Minus!1, Y=2}");
}
finally {
Thread.CurrentThread.CurrentCulture = preCulture;
}
}
但是对于 Size 类我不能这样做,因为 Width 和 Height 不能为负数,所以我需要创建一个 CultureInfo 实例,其中正数不包含 {1,2,3,4,5,6, 7,8,9,0}。
如果没有这样的文化,我只是不需要这个 Size 类的测试。
目前还不清楚问题是什么,甚至这里正在测试什么。 ToString
仅添加{X=..., Y=...}
模板,其余的被委托给字段类型(例如decimal
或double
)。 在Point.ToString()
或Size.ToString()
单元测试中没有点单元测试decimal.ToString()
。
基类库中的本地化敏感类无论如何都接受CultureInfo
参数,它们不依赖于当前环境文化。 在很多情况下,当前的文化不一定是我们真正想要的文化,例如在 Web 应用程序中,或者当我们想要在特定语言环境中读取或写入文件时。
最好有一个其他人委托给的ToString(CultureInfo)
方法。 这将简化测试并减少重复。 使用String.Format
将进一步减少代码并减少出错的机会:
public string ToString(CultureInfo culture)
{
return String.Format(culture,"{X={0}, Y={1}}",X,Y);
}
public override string ToString()=>ToString(CultureInfo.CurrentCulture);
//Really, this should be ToStringUS();
public string ToStringInvariant()=>ToString(CultureInfo.InvariantCulture);
格式字符串可以有不同的部分来为负数或零指定不同的格式,例如:
"{X={0:#;(#)}, Y={1:#;(#)}}"
或者
"{X={0:#;Minus!#;**Zero**}, Y={1:#;Minus!#;**Zero**}}"
Rant : InvariantCulture
本质上是美国文化。 数字可以,但在格式化日期时会成为一个严重的问题。 它不是标准的 YYYY-MM-DD 格式,而是生成美国风格的日期。
无论方法如何实现,唯一需要单元测试的部分是该方法的输出,而不是decimal
本身的格式。
[TestCase("en-US","{X=-1.5, Y=2.6}")
[TestCase("en-UK","{X=-1,5, Y=2,6}")
public void ToString_Is_Locale_Aware(string culture,string expected)
{
var ci=CultureInfo.GetCulture(culture);
var point=new Point(-1.5,2.6);
var actual=point.ToString(ci);
Assert.AreEqual(expected,actual);
}
[TestCase("en-US","{X=-1.5, Y=2.6}")
[TestCase("en-UK","{X=-1,5, Y=2,6}")
public void ToStringBase_Is_Locale_Aware(string culture,string expected)
{
var point=new Point(-1.5,2.6);
var ci=CultureInfo.GetCulture(culture);
var preCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = ci;
var actual=point.ToString();
Assert.AreEqual(expected,actual);
}
finally {
Thread.CurrentThread.CurrentCulture = preCulture;
}
}
测试ToStringInvariant
只需要证明字符串不会改变
[TestCase("en-US")
[TestCase("en-UK")
[TestCase("de-DE")
public void ToStringInvariant_Is_Locale_Unaware(string culture)
{
var point=new Point(-1.5,2.6);
var ci=CultureInfo.GetCulture(culture);
var preCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = ci;
var actual=point.ToStringInvariant();
Assert.AreEqual("{X=-1.5, Y=2.6}",actual);
}
finally {
Thread.CurrentThread.CurrentCulture = preCulture;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.