【问题标题】:Mocking a random return value in ASP.NET MVC for SpecFlow在 ASP.NET MVC 中为 SpecFlow 模拟随机返回值
【发布时间】:2015-03-31 20:37:58
【问题描述】:

我正在使用 Specflow 和 WebDriver 来测试我的 ASP.Net MVC 应用程序。

我想在我的高级 Specflow 测试中使用带有 ASP.Net MVC 的模拟。这将用于将应用程序设置为已知状态。

在 ASP.Net 应用程序中,有一个类,它带有一个返回随机值的方法。我想模拟这个类,以便我知道将返回什么值,并且我知道在测试中会发生什么。

请注意,这不能通过使用数据库数据来完成。随机性不受数据库影响。

我知道这可以在较低级别的测试(如控制器测试和其他单元测试)中完成,但是我想知道如何从 Specflow 中做到这一点。某种形式的依赖注入会很好。

我已阅读有关 Deleporter 的信息,但该项目似乎处于非活动状态。如果不是,请纠正我。

你有什么建议吗?

谢谢

【问题讨论】:

  • 您要更改已部署网站的状态吗?
  • 要么自己托管,要么托管在内存中。只要我能对它进行测试。
  • @Daryn:也许您可以将问题的标题更改为“Mocking random value in ASP.NET MVC for SpecFlow”?

标签: c# asp.net-mvc mocking ui-automation specflow


【解决方案1】:

编辑:由于您需要从 MVC 应用程序中了解 SpecFlow 中的随机值,因此您不需要“模拟”,而是需要一个存根(以及一些小巫术)。

在 ASP.NET MVC 中存根一个随机值,以便 SpecFlow 可以使用它

  1. 创建一个您的随机值生成器将实现的接口
  2. 在您的 MVC 项目中创建另一个实现此接口的类,但返回您的 SpecFlow 测试可以使用的已知值
  3. 在您的 MVC 应用程序的 App.config 文件中添加一个 <appSetting>,以便您指定返回此随机值的具体类
  4. 在您的 MVC 应用程序中创建一个工厂类,该类读取配置设置并返回一个实现您的随机值接口的对象:

下面的接口和类只是供您学习的示例。我假设您正在生成一个随机的int,但可以使用以下解决方案作为模板来解决您的问题。

创建界面

这个简单的接口只有一个返回int 的方法。没有别的了。

public interface IRandomValueGenerator
{
    int GenerateRandomValue();
}

创建实现接口的类

您需要创建返回已知值的“存根”类,并确保您现有的类实现了该接口。

首先,为了测试目的返回一致值的假随机数生成器:

public class FakeRandomValueGenerator : IRandomValueGenerator
{
    public int GenerateRandomValue()
    {
        return 5;
    }
}

现在,确保你的真实类实现了这个接口:

public class RealRandomValueGenerator : IRandomValueGenerator
{
    public int GenerateRandomValue()
    {
        return new System.Random().Next();
    }
}

将设置添加到 App.config

接下来,您想让随机值生成器可配置,以便在生产中使用真正的生成器,但在集成测试环境中使用存根:

应用程序配置
<appSettings>
  <!--
    Values:
    - random (for deployed sites)
    - fake (for the integration testing environment)
  -->
  <add key="randomValueGenerator" value="fake" />

创建工厂类以返回值生成器

最后一步是创建一个工厂类,它读取您的配置并为IRandomValueGenerator 接口返回一个具体类型。

public static class RandomValueGeneratorFactory
{
    public static IRandomValueGenerator GetGenerator()
    {
        string type = System.Configuration.ConfigurationManager.AppSettings["randomValueGenerator"];
        IRandomValueGenerator valueGenerator;

        switch (type)
        {
            case "random":
                valueGenerator = new RealRandomValueGenerator();
                break;
            case "fake":
                valueGenerator = new FakeRandomValueGenerator();
                break;
            default:
                throw new System.Configuration.ConfigurationException("Unsupported value for randomValueGenerator: " + type);
        }

        return valueGenerator;
    }
}

拼凑起来

现在您需要更改您的 MVC 应用程序代码以使用工厂:

public class FooController : Controller
{
    public ActionResult Create()
    {
        IRandomValueGenerator generator = RandomValueGeneratorFactory.GetGenerator();
        int value = generator.GenerateRandomValue();

        // Do other stuff

        return View(...);
    }
}

依赖注入

您提到依赖注入将是一个很好的解决方案。通过声明一个用于生成随机数的接口,您可以为依赖注入进行设置——但我将其作为练习留给您!

【讨论】:

  • 感谢您抽出宝贵时间回答。正如我的问题所述,使用数据库不是一种选择。我有一个非确定性的课程。此类不受数据库的任何影响。我想模拟或存根这个功能。这将允许我测试应用程序的其余部分。
  • @Daryn:你能用更多关于这个“非确定性”类的信息来更新你的问题吗?您能否也给我们这个类的用例?这可能有助于制定解决方案。
  • @Daryn:我已经根据对您问题的编辑完全重写了我的答案。
【解决方案2】:

如果您真的无法使用数据库实现什么,那么一个丑陋的选择可能是允许您的测试使用可选的 url 参数调用您的网页,该参数指定要使用的测试配置,然后在您的代码中根据该值选择一个实现在这个参数中。这可能是您只想在代码的调试版本中执行的操作,并且不想在生产中允许。

或者,您可以调用一个不同的 URL 来设置应用程序的测试状态,然后您的其他 url 不需要更改,测试 URL 可以从生产中排除。然后,您可以从 specflow 步骤中调用它(可能在 Given I am using test state 'someConfigName' 中)。

如果您可以使用 ASP vNext 作为自托管解决方案,您可能还会获得一些价值。有了这个,应该可以让 specflow 使用[Before] 步骤来设置自主机,并使用[After] 步骤来拆除它。如果没有 ASP vNext,我认为自托管是不可能的。

【讨论】:

    猜你喜欢
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多