如何编写递归方法的Mockist测试

Jer*_*eir 8 unit-testing rhino-mocks moq mocking

如果我有一个在某种条件下调用自己的方法,是否可以编写测试来验证行为?我很想看到一个例子,我不关心模拟框架或语言.我在C#中使用RhinoMocks所以我很好奇它是否是框架的缺失特征,或者我是否误解了一些基本的东西,或者它是否是不可能的.

Dmy*_*iak 6

在某种条件下调用自身的方法,是否可以编写测试来验证行为?

是.但是,如果需要测试递归,最好将入口点分为递归和递归步骤以进行测试.

无论如何,如果你不能这样做,这里是如何测试它的例子.你真的不需要任何嘲笑:

// Class under test
public class Factorial
{
    public virtual int Calculate(int number)
    {
        if (number < 2)
            return 1
        return Calculate(number-1) * number;
    }
}

// The helper class to test the recursion
public class FactorialTester : Factorial
{
    public int NumberOfCalls { get; set; }

    public override int Calculate(int number)
    {
        NumberOfCalls++;
        return base.Calculate(number)
    }
}    

// Testing
[Test]
public void IsCalledAtLeastOnce()
{
    var tester = new FactorialTester();
    tester.Calculate(1);
    Assert.GreaterOrEqual(1, tester.NumberOfCalls  );
}
[Test]
public void IsCalled3TimesForNumber3()
{
    var tester = new FactorialTester();
    tester.Calculate(3);
    Assert.AreEqual(3, tester.NumberOfCalls  );
}
Run Code Online (Sandbox Code Playgroud)


mia*_*biz 4

假设您想要执行类似从完整路径获取文件名的操作,例如:

c:/windows/awesome/lol.cs -> lol.cs
c:/windows/awesome/yeah/lol.cs -> lol.cs
lol.cs -> lol.cs
Run Code Online (Sandbox Code Playgroud)

你有:

public getFilename(String original) {
  var stripped = original;
  while(hasSlashes(stripped)) {
    stripped = stripped.substringAfterFirstSlash(); 
  }
  return stripped;
}
Run Code Online (Sandbox Code Playgroud)

你想写:

public getFilename(String original) {
  if(hasSlashes(original)) {
    return getFilename(original.substringAfterFirstSlash()); 
  }
  return original;
}
Run Code Online (Sandbox Code Playgroud)

这里的递归是一个实现细节,不应进行测试。您确实希望能够在两个实现之间切换并验证它们是否产生相同的结果:对于上面的三个示例,两者都生成 lol.cs。

话虽这么说,因为您是按名称递归,而不是说 thisMethod.again() 等,所以在 Ruby 中您可以将原始方法别名为新名称,使用旧名称重新定义方法,调用新名称并检查是否你最终会进入新定义的方法。

def blah
  puts "in blah"
  blah
end

alias blah2 blah

def blah
  puts "new blah"
end

blah2
Run Code Online (Sandbox Code Playgroud)