C# 在ASP.NET MVC中模拟SpecFlow的随机返回值

C# 在ASP.NET MVC中模拟SpecFlow的随机返回值,c#,asp.net-mvc,mocking,ui-automation,specflow,C#,Asp.net Mvc,Mocking,Ui Automation,Specflow,我正在使用Specflow和WebDriver测试我的ASP.NETMVC应用程序 我想在我的高级Specflow测试中使用ASP.NETMVC模拟。这将用于将应用程序设置为已知状态 在ASP.Net应用程序中,有一个类,其方法返回一个随机值。我想模拟这个类,这样我就知道将返回什么值,并且知道在测试中预期会发生什么 注意,这不能通过使用数据库数据来完成。随机性不受数据库的影响 我知道这可以在较低级别的测试中完成,比如控制器测试和其他单元测试,但是我想知道如何从Specflow中完成。某种形式的依

我正在使用Specflow和WebDriver测试我的ASP.NETMVC应用程序

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

在ASP.Net应用程序中,有一个类,其方法返回一个随机值。我想模拟这个类,这样我就知道将返回什么值,并且知道在测试中预期会发生什么

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

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

我读过关于Deleporter的文章,但该项目似乎处于停滞状态。如果不是,请纠正我

你有什么建议给我吗


谢谢编辑:因为您需要从MVC应用程序中知道SpecFlow中的随机值,所以您不需要模拟,相反,您需要一个存根和一些鸡巫术

在ASP.NET MVC中存根一个随机值,以便SpecFlow可以使用它 创建随机值生成器将实现的接口 在MVC项目中创建另一个实现此接口的类,但返回SpecFlow测试可以使用的已知值 在App.config文件中为MVC应用程序添加一个,允许您指定返回此随机值的具体类 在MVC应用程序中创建一个factory类,该类读取配置设置并返回实现随机值接口的对象: 下面的接口和类只是供您学习的示例。我假设您正在生成一个随机int,但是下面的解决方案可以用作解决问题的模板

创建接口 这个简单的接口只有一个返回int的方法,其他什么都没有

public interface IRandomValueGenerator
{
    int GenerateRandomValue();
}
创建类来实现接口 您需要创建返回已知值的存根类,并确保现有类实现该接口

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;
    }
}
首先,伪随机数生成器返回一致的值以进行测试:

public class FakeRandomValueGenerator : IRandomValueGenerator
{
    public int GenerateRandomValue()
    {
        return 5;
    }
}
现在,请确保您的真实类实现此接口:

public class RealRandomValueGenerator : IRandomValueGenerator
{
    public int GenerateRandomValue()
    {
        return new System.Random().Next();
    }
}
将设置添加到App.config 接下来,您希望使随机值生成器可配置,以便在生产中使用真实的生成器,但在集成测试环境中使用存根:

App.config 拼凑 现在,您需要更改MVC应用程序代码以使用工厂:

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

        // Do other stuff

        return View(...);
    }
}
依赖注入
您提到依赖注入将是一个很好的解决方案。通过声明一个用于生成随机数的接口,您将自己设置为依赖项注入,但我将此作为一个练习留给您

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

或者,您可以调用一个不同的URL来设置应用程序的测试状态,然后您的其他URL不需要更改,测试URL可以从生产中排除。然后,您可以在给定的“我正在使用”测试状态“someConfigName”中,从specflow步骤调用此函数


如果可以使用ASP vNext作为自托管解决方案,您可能也会获得一些价值。这样,specflow就可以使用[Before]步骤设置自身主机,并使用[After]步骤将其拆除。如果没有ASP vNext,我认为不可能自托管。

是否要更改已部署网站的状态?或者,它可以自托管,或者托管在内存中。只要我能对它进行测试。@Daryn:也许你可以把你的问题的标题改为在ASP.NET MVC for SpecFlow中模拟随机值?谢谢你花时间回答。正如我在问题中所说,使用数据库不是一种选择。我有一个不确定的类。这个类不受数据库的任何影响。我想模拟或存根此功能。这将允许我测试应用程序的其余部分。@Daryn:你能用关于这个非确定性类的更多信息更新你的问题吗?你能给我们这个类的用例吗?这可能有助于制定一个解决方案。@Daryn:我已经完全根据对你问题的编辑改写了我的答案。
public class FooController : Controller
{
    public ActionResult Create()
    {
        IRandomValueGenerator generator = RandomValueGeneratorFactory.GetGenerator();
        int value = generator.GenerateRandomValue();

        // Do other stuff

        return View(...);
    }
}