使用FakeItEasy和FluentValidation从commonlibnet伪造的验证码 [英] Fake Captcha from commonlibnet with FakeItEasy and FluentValidation

查看:134
本文介绍了使用FakeItEasy和FluentValidation从commonlibnet伪造的验证码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用来自公共库(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伪造静态方法.

TIA,

大卫

解决方案

在FakeItEasy中无法拦截静态方法(并且目前尚无其他开放源代码,.Net的免费模拟框架).为了能够模拟静态(和密封类),您必须从Telerik购买Typemock隔离器或Just Mock.

许多开发人员认为静态是代码气味(在大多数情况下).因此,开源模拟框架不支持此事实是一件好事,因为它促进了更好的设计.模拟的黄金法则"是如果您无法控制它就不要模拟它",因此解决您遇到的问题的常用方法是围绕静态调用创建包装器.您可以使用此-模拟-包装器测试互动. System.DateTime.Now是您经常在测试中要测试的静态示例.要从中隔离测试,您可以执行以下操作:

public interface ISystemTimeProvider
{
    DateTime Now { get; }
}

public class DateTimeNowSystemTimeProvider
    : ISystemTimeProvider
{
    public DateTime Now
    {
        get
        {
            return DateTime.Now;
        }
    }
}

使用上述接口和实现,您的SUT将依赖于该接口(例如,通过构造函数注入).在您的测试中,您将使用伪造的(A.Fake<ISystemTimeProvider>())对其进行注入. DateTimeSystemTimeProvider的实现永远不会进行单元测试,它的级别很低,除了集成测试之外,不需要其他任何测试.

我对您所讨论的验证码库不是很熟悉,因此我不确定在这种情况下如何正确应用上述模式,但是我敢肯定可以用一种或另一种方式来实现./p>

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

解决方案

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:

public interface ISystemTimeProvider
{
    DateTime Now { get; }
}

public class DateTimeNowSystemTimeProvider
    : ISystemTimeProvider
{
    public DateTime Now
    {
        get
        {
            return DateTime.Now;
        }
    }
}

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.

这篇关于使用FakeItEasy和FluentValidation从commonlibnet伪造的验证码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆