使用 FakeItEasy 和 FluentValidation 从 commonlibnet 伪造验证码
我正在使用 commonlibrary (http://commonlibrarynet.codeplex.com/) 中的 Captcha 类。我的代码可以工作,但现在我正在尝试编写单元测试。
我的验证规则是:
RuleFor(x => x.CaptchaUserInput)
.NotEmpty()
.Must((x, captchaUserInput) => Captcha.IsCorrect(captchaUserInput, x.CaptchaGeneratedText))
.WithMessage("Invalid captcha code");
在我的设置代码中,我尝试执行以下操作:
A.CallTo(() => Captcha.IsCorrect()).Returns(true);
但收到以下错误消息:
SetUp : FakeItEasy.Configuration.FakeConfigurationException :
The current proxy generator can not intercept the specified method for the following reason:
- Static methods can not be intercepted.
at FakeItEasy.Configuration.DefaultInterceptionAsserter.AssertThatMethodCanBeInterceptedOnInstance(Metho dInfo method, Object callTarget)
at FakeItEasy.Configuration.FakeConfigurationManager.CallTo(Expression`1 callSpecification)
at ProdMaster.Hosts.Web.Tests.Unit.Controllers.AccountControllerTests.SetUp() in AccountControllerTests.cs: line 44
所以问题实际上是如何使用 FakeItEasy 伪造静态方法。
蒂亚,
大卫
I am using the Captcha class from commonlibrary (http://commonlibrarynet.codeplex.com/). My code works and everything but now I'm trying to write the unit test.
My validation rule is:
RuleFor(x => x.CaptchaUserInput)
.NotEmpty()
.Must((x, captchaUserInput) => Captcha.IsCorrect(captchaUserInput, x.CaptchaGeneratedText))
.WithMessage("Invalid captcha code");
In my set up code I tried to do the following:
A.CallTo(() => Captcha.IsCorrect()).Returns(true);
but I get the following error message:
SetUp : FakeItEasy.Configuration.FakeConfigurationException :
The current proxy generator can not intercept the specified method for the following reason:
- Static methods can not be intercepted.
at FakeItEasy.Configuration.DefaultInterceptionAsserter.AssertThatMethodCanBeInterceptedOnInstance(Metho dInfo method, Object callTarget)
at FakeItEasy.Configuration.FakeConfigurationManager.CallTo(Expression`1 callSpecification)
at ProdMaster.Hosts.Web.Tests.Unit.Controllers.AccountControllerTests.SetUp() in AccountControllerTests.cs: line 44
So the question really is how to fake static methods using FakeItEasy.
TIA,
David
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 FakeItEasy 中无法拦截静态方法(目前在 .Net 上没有其他开源、免费的模拟框架)。为了能够模拟静态(和密封类),您必须从 Telerik 购买 Typemock Isolator 或 Just Mock。
许多开发人员认为静态是代码味道(在大多数情况下)。因此,开源模拟框架不支持这一点被视为一件好事,因为它可以促进更好的设计。模拟的“黄金法则”是“如果你无法控制它,就不要模拟它”,因此解决遇到的问题的常见方法是围绕静态调用创建一个包装器。您可以测试与此可模拟包装器的交互。 System.DateTime.Now 是您经常希望在测试中进行测试的静态示例。为了将你的测试与此隔离,你可以这样做:
使用上面的接口和实现,你的 SUT 将依赖于接口(例如通过构造函数注入)。在您的测试中,您将使用假值 (
A.Fake()
) 注入它。 DateTimeSystemTimeProvider 的实现永远不会进行单元测试,它的级别非常低,除了集成测试之外不需要任何测试。我对您正在谈论的验证码库不是很熟悉,所以我不确定在这种情况下您将如何应用上述模式,但我确信可以通过一种或另一种方式完成。
There's no way to intercept static methods in FakeItEasy (and currently in no other opens source, free mocking framework for .Net). To be able to mock statics (and sealed classes) you would have to purchase either Typemock Isolator or Just Mock from Telerik.
Many developers consider statics to be code smell (in most cases). So the fact that open source mocking frameworks do not support this is seen as a good thing since it promotes better designs. A "golden rule" of mocking is "if you can't control it don't mock it" so the common way of going about the problem you've run into is to create a wrapper around the static calls. You test the interaction with this - mockable - wrapper. System.DateTime.Now is an example of a static that you'd often like to test against in your tests. To isolate your tests from this you'd do something like this:
With the above interface and implementation your SUT would depend on the interface (for example through constructor injection). In your tests you would inject it with a fake (
A.Fake<ISystemTimeProvider>()
). The implementation of DateTimeSystemTimeProvider would never be unit tested, it's very low level and shouldn't need any tests really other than integration tests.I'm not very familiar with the captcha library you're talking about so I'm not sure exactly how you would apply the above pattern in that case but I'm sure it can be done one way or another.
与 Patrik 的解决方案类似,您只需将委托传递到调用此静态方法的类的构造函数中即可。
因此,您需要在默认构造函数中设置一个指向 Captcha.IsCorrect 的委托。
该委托变量将在您的 fluidValidation 代码中调用。在单元测试时,您将创建一个新的构造函数,在其中将委托设置为指向您的模拟方法。 (在你的情况下,只需返回 true )
Similar to Patrik's solution, you can just pass a delegate into the constructor of your class that calls this static method.
So you'd setup a delegate in your default constructor pointing to Captcha.IsCorrect.
This delegate variable will be called within your fluentValidation code. While unit testing you will create a new constructor where you will set the delegate to point to your mock method. (in your case, just return true)