测试常量的所有可能值

时间:2012-11-01 13:46:17

标签: c# unit-testing constants mstest

我的应用程序中有一个常量,它决定了程序其他部分的操作。我更改此常量以快速轻松地改变程序的操作。

在我的例子中,常量是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次测试。
  • 不要让它成为常数。在测试方法中,首先将constant设置为true,断言,然后设置为false,再次断言。但是,我首先使它成为一个常数的原因是它保证不会在运行时改变。

我想我真正想要的是一种方法,就应用本身而言,它是不变的,但就测试项目而言,并不是一个常数。

那我怎么能做出像这样的工作呢?

3 个答案:

答案 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)

使用枚举而不是常量。这样你可以防止它被改变为意想不到的东西,但它可以修改并且可以用更多的值进行扩展。