在 SpecFlow 的 ASP.NET MVC 中模拟随机 return 值

Mocking a random return value in ASP.NET MVC for SpecFlow

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

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

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

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

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

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

你有什么指点吗?

谢谢

编辑:由于您需要从 MVC 应用程序中了解 SpecFlow 中的随机值,因此您不需要 "mock,",而是需要一个存根(和一些鸡巫毒魔法)。

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

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

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

创建界面

这个简单的界面只有一个方法,return是一个int。没有别的。

public interface IRandomValueGenerator
{
    int GenerateRandomValue();
}

创建 classes 来实现接口

您需要创建 "stub" class return 已知值,并确保您现有的 class 实现了接口。

首先,伪造的随机数生成器return是一个用于测试目的的一致值:

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

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

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

将设置添加到 App.config

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

App.config
<appSettings>
  <!--
    Values:
    - random (for deployed sites)
    - fake (for the integration testing environment)
  -->
  <add key="randomValueGenerator" value="fake" />

创建工厂 class 到 return 值生成器

最后一步是创建工厂 class 来读取您的配置,return 是 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(...);
    }
}

依赖注入

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

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

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

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