如何在测试配方函数时自动消除依赖关系
我有一个函数 foo(),它又调用函数 bar()。我如何确认 bar 确实被调用了?
要测试的复杂业务逻辑方法的示例:
class Car
{
IStarter starter
IKeyhole keyhole
IBrakePedal pedal
Drive()
{
keyhole.InsertKey()
keyhole.RotateToStart()
starter.TurnEngineOver()
...
if (pedal.Pressed)
this.SlowDown()
}
}
我有一个方法,它汇集了6个外部依赖项(与方法的接口),并按顺序运行它们,顺序并不重要。我想确保每个人都被叫到了。在另一个测试中,我想调整条件并确保调用一个子集。
在带有 Moq 的 C# 中,我有一整页的设置代码。
这是我希望在单元测试中看到的内容:
let `check that brake pedal slows down car` =
let car = new Car()
car.pedal.Pressed <- true
car.Drive()
car.SlowDown |> wasCalled
其余的应该从使用情况中推断出来。我确实需要减少测试中的噪音。
I have a function foo() that in turn calls function bar(). How can I confirm that bar actually gets called?
Example of complex business logic method to test:
class Car
{
IStarter starter
IKeyhole keyhole
IBrakePedal pedal
Drive()
{
keyhole.InsertKey()
keyhole.RotateToStart()
starter.TurnEngineOver()
...
if (pedal.Pressed)
this.SlowDown()
}
}
I have a method that brings together 6 external dependencies (interfaces with methods), and runs them in a sequence, order is not important. I would like to make sure each was called. In another test, I'd like to tweak conditionals and ensure that a subset was called.
In C# with Moq, I have a full page of setup code.
Here's what I'd like to see in my unit test:
let `check that brake pedal slows down car` =
let car = new Car()
car.pedal.Pressed <- true
car.Drive()
car.SlowDown |> wasCalled
The rest should be inferred from usage. I have a real need to reduce noise in tests.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我知道最接近您想要的是 AutoMockingContainer。
简而言之,它是一个 IoC 容器,为您提供了一辆 Car,其中所有 IStarter、IKeyhole、IBrakepedal 都被拔掉并连接到 Car 实例,而无需您显式注册它们中的任何一个。然后,您继续照常设置您的期望(在您的情况下,“car.SlowDown() 被调用”),然后调用被测试的方法。
具体细节取决于所使用的 IoC 容器和模拟框架。最初的版本是用 Windsor 和旧版本的 Rhino Mocks 编写的,但现在有用于 StructureMap、Ninject、Autofac + Moq 等
。可以从其中之一开始,然后将其包装起来,使其在 F# 中更加惯用。
它 有 其 缺点,我不建议使用“默认”。
The closest thing I know to what you want is an AutoMockingContainer.
In a nutshell, it's an IoC container that gives you a Car with all IStarter, IKeyhole, IBrakepedal stubbed out and wired to the Car instance, without you explicitly registering any of them. You then proceed to set your expectations as usual (in your case, "car.SlowDown() was called"), then call the method under test.
The specifics depend on the IoC container and mocking framework used. The original one was written with Windsor and an old version of Rhino Mocks, but now there are AMC for StructureMap, Ninject, Autofac + Moq, etc.
You could start with one of these and wrap it to make it more idiomatic in F#.
It has its downsides, it's not something I'd recommend using "by default".