我的应用程序中有一个常量,它决定了程序其他部分的操作。我更改此常量以快速轻松地改变程序的操作。
在我的例子中,常量是bool
,所以它可以有两个值中的一个。
我想编写一个测试,确保我的代码工作是否将常量设置为true。
例如,说我的方法是这样的:
public boolean IsEqual(float a, float b) {
var epsilon = 0.0001;
if (Constants.Exact) return (Math.Abs(a-b) < epsilon);
else return (Math.Floor(a) == Math.Floor(b));
}
Constants
看起来像这样:
public static class Constants {
/// <summary>
/// Determines whether an exact comparison should be made, or whether fractional parts should be disregarded.
/// </summary>
public const bool Exact = true;
}
测试方法是:
[TestMethod]
public void TestEquality() {
var five = 5;
var three = 3;
Assert.True(Equals(five, three));
}
我能提出的解决方案:
true
并运行测试,然后将其设置为false并运行测试。不好,因为如果我有8个这样的常量,我不想运行256次测试。我想我真正想要的是一种方法,就应用本身而言,它是不变的,但就测试项目而言,并不是一个常数。
那我怎么能做出像这样的工作呢?
答案 0 :(得分:3)
创建函数的两个重载,一个带有额外的exact
参数,另一个带有Exact
常量隐式
public bool IsEqual(float a, float b)
{
return IsEqual(a, b, Constants.Exact);
}
public bool IsEqual(float a, float b, bool exact)
{
if (exact)
return a == b;
else
return Math.Floor(a) == Math.Floor(b);
}
现在,您可以在不依赖预定义常量的情况下测试excat
的任何值。
IEquatable<float>
更新(请参阅评论)
IEquatable<T>.Equals
只有一个参数。因此,我假设在此示例中将另一个值定义为属性Value
public float Value { get; set; }
#region IEquatable<float> Members
public bool Equals(float other)
{
return Equals(other, Constants.Exact);
}
#endregion
public bool Equals(float other, bool exact)
{
if (exact)
return Value == other;
else
return Math.Floor(Value) == Math.Floor(other);
}
答案 1 :(得分:1)
你可以在内部创建常量并通过属性表示它,所以你说
private const bool _exact = false;
public bool Exact
{
get { return _exact };
set { throw new Exception("Don't set this, you crazy donkey") };
}
然后,为了进行测试,您可以创建一个继承自常量类的类,但会覆盖Exact
属性。只要你通过它在父类中面向公众的名称来调用它,那么你应该能够改变测试中的值并在常规实现中保持它不变。
编辑:事实上,如果你的常量都是在一个类中定义的,那么最好的工作方式是简单地从该类中提取界面,然后你可以在测试时切换实现(或任何其他如果你是使用某种DI框架)或简单地使用模拟框架来模拟给定测试所需的任何部分。
答案 2 :(得分:0)
使用枚举而不是常量。这样你可以防止它被改变为意想不到的东西,但它可以修改并且可以用更多的值进行扩展。