2010-04-09 57 views
1

我试图建立与犀牛嘲笑存根返回基于值是什么传入的参数的参数从参数返回一个复杂数据类型与犀牛嘲笑

例:

//Arrange 
var car = new Car(); 
var provider= MockRepository.GenerateStub<IDataProvider>(); 
provider.Stub(
    x => x.GetWheelsWithSize(Arg<int>.Is.Anything)) 
    .Return(new List<IWheel> { 
       new Wheel { Size = ?, Make = Make.Michelin }, 
       new Wheel { Size = ?, Make = Make.Firestone } 
      }); 

car.Provider = provider; 

//Act 
car.ReplaceTires(); 

//Assert that the right tire size was used when replacing the tires 

问题是我希望Size是被传递到方法中的任何东西,因为我后来实际上声称轮子尺寸合适。这并不是为了证明数据提供者工作起来很明显,因为我把它扼杀了,而是证明正确的大小通过了。

我该怎么做?

回答

1

“这不是证明数据提供商合作......而是要证明 正确的大小被通过了。“

不确定它是否适用于这种特殊情况,但通常我发现通过存根间接测试这些事情是最容易的。

不是检查存根调用的输出,而是明确指定存根的参数,然后验证是否按预期使用了返回值(与返回的实际数据无关)。如果是,那么你知道你的存根被正确地调用了。

//Arrange 
var wheels = new List<IWheel>(); 
const int wheelSize = 17; 
var car = new Car(); 
car.WheelSize = wheelSize; 
var provider= MockRepository.GenerateStub<IDataProvider>(); 
provider 
    .Stub(x => x.GetWheelsWithSize(wheelSize)) 
    .Return(wheels);  
car.Provider = provider; 

//Act 
car.ReplaceTires(); 

//Assert that the right-sized wheels from the provider were 
//used when replacing the tires 
Assert.That(car.Wheels, Is.SameAs(wheels)); 

如果这个方法不适合你在这种情况下工作,那么你可以使用WhenCalled to inspect the call arguments and/or modify the return value

provider 
    .Stub(x => x.GetWheelsWithSize(Arg<int>.Is.Anything)) 
    .WhenCalled(x => x.ReturnValue = CreateWheelsOfSize((int) x.Arguments[0])); 

在这种情况下,CreateWheelsOfSize(int)将刚刚创建您的轮子列表。

希望这会有所帮助。

+0

@David WhenCalled是我最终必须采取的确切方法。它允许我确保我将参数传递给模拟,然后再进行验证。如果有一些方法可以使用WhenCalled功能而无需使用Return功能,或者可能只是以某种方式将它们合并在一起,那将会非常棒。 – Joseph 2010-04-12 01:57:27

+0

@Joseph, 避免必须使用WhenCalled/Return的最简单的方法是确保控制传递给GetWheelsWithSize的值(而不是使用Arg .Is.Anything),因此我的答案中提出了第一个建议。如果你无法获得它的价值,那么它可能是值得重构的,这样逻辑就是孤立的,并且是单元可测试的。 – 2010-04-12 02:41:24

1

您可以使用Do()功能来实现动态返回值。例如:

[Test] 
public void DynamicallyFakeReturnValue() 
{ 
    var calculatorStub = MockRepository.GenerateStub<ICalculator>(); 
    calculatorStub.Stub(address => address.AddOne(Arg<int>.Is.Anything)) 
     .Do((Func<int, int>) (x => x - 1)); 

    Assert.That(calculatorStub.AddOne(1), Is.EqualTo(0)); 
} 

在你的情况下,它可能会是:

provider.Stub(
    x => x.GetWheelsWithSize(Arg<int>.Is.Anything)) 
    .Do((Func<int, List<IWheel>>) (size => new List<IWheel> { 
       new Wheel { Size = size, Make = Make.Michelin }, 
       new Wheel { Size = size, Make = Make.Firestone } 
      }));