如何在PHPSpec规范文件中创建类变量,该文件可用于规范

时间:2017-09-18 20:14:57

标签: laravel factory phpspec

我有一个PHPSpec类,里面有很多例子。我希望能够在spec类中创建类变量,可以由类中的任何示例函数使用。

以下是一个非常简化的版本:

class ThingImTestingSpec extends ObjectBehavior
{
    private $common_variables_array = [
        'property_1' => value_1,
        'property_2' => 'Value 2'
    ];

    function it_finds_a_common_property()
    {
        $object_1 = new ConstructedObject;

        $this->find_the_common_property($object_1)->shouldReturn($this->common_variables_array['property_1']);
    }
}

问题在于PHPSpec(巧妙地)如何实例化并引用被测试的类。 spec方法中对$this的引用实际上是指测试对象,不是 spec类本身。

但这意味着尝试使用$this->class_variable引用类变量来引用测试对象上的类变量,而不是规范。

因此。如何在spec类本身的范围内创建一组变量,这些变量可以在运行时由示例访问?

我尝试过的事情:

  • 将类变量放在构造函数中 - 仍然无法通过示例
  • 访问
  • 使用beConstructedWith - 需要更改被测试的类,以便进行测试。不是一个干净的解决方案。
  • 当我想引用的公共对象是数据库记录时,我可以使用Eloquent通过id(或其他属性)引用它们,每次都从Model中构建一个集合或类对象。 这很有用,但很耗时,因为我需要在每个spec函数中构建集合或对象。我想在实例化规范类时构建这些集合和对象,并在整个类中引用它们。

我尚未尝试的事情:

  • 创建spec类和被测试类范围之外的第三个对象,以容纳通用对象和变量,这些对象和变量可以在运行时由spec类方法(示例)访问。这个解决方案可以工作,但如果有更清洁的解决方案,它会为我想避免的规格添加一层。

注意:我不是在寻找以上述方式进行测试的“替代方案”,除非它们仍然适合更广泛的需求。这个例子非常简单。在实践中,我正在扩展LaravelObjectBehaviorhttps://github.com/BenConstable/phpspec-laravel),使用spec的构造函数通过Factory和Faker类(https://github.com/thephpleague/factory-muffin)在测试数据库中创建记录,并在测试后销毁它们(在规范的析构函数中的League \ FactoryMuffin \ Facade :: deleteSaved())。我希望能够在任意数量的spec函数中引用Model所代表的对象(并由FactoryMuffin创建),因此我不必在每个spec函数中重新创建这些对象和集合。是的,我知道这个步骤超出了“规范”测试的范围,但是当应用程序被绑定到模型时,与数据层交互的对象仍然是“可指定的”,可以争论。

我目前正在使用phpspec 2.2.1和Laravel 4.2

2 个答案:

答案 0 :(得分:2)

我们目前在我们的软件中使用PHPSpec v3。请使用let方法声明常见内容。快速举例:

<?php

class ExampleSpec extends \PhpSpec\ObjectBehavior
{
    private $example; // private property in the spec itself

    function let()
    {
        $this->example = (object) ['test1' => 'test1']; // setting property of the spec
        parent::let();
    }

    function it_works()
    {
        var_dump($this->example); // will dump: object(stdClass)#1 (1) { ["test1"] => string(5) "test1" }
    }

    function it_works_here_as_well()
    {
        var_dump($this->example); // will dump same thing as above: object(stdClass)#1 (1) { ["test1"] => string(5) "test1" }
        $this->example = (object) ['test2' => 'test2']; // but setting here will be visible only for this example
    }

    function it_is_an_another_example()
    {
        var_dump($this->example); // will dump same thing first two examples: object(stdClass)#1 (1) { ["test1"] => string(5) "test1" }
    }
}

答案 1 :(得分:1)

找到答案。明确地将类变量声明为static,并且可以通过spec类中的方法访问它们:

class ThingImTestingSpec extends ObjectBehavior
{
    private static $common_variables_array = [
        'property_1' => value_1,
        'property_2' => 'Value 2'
    ];

    function it_finds_a_common_property()
    {
        $object_1 = new ConstructedObject;

        $this->find_the_common_property($object_1)->shouldReturn($this::$common_variables_array['property_1']);
    }
}

这适用于数组以及表示使用Eloquent构建的数据库记录的对象,例如

class LaravelAppClassImTestingSpec extends LaravelObjectBehavior
{
    private static $Order_1;

    function __construct()
    {
        $Order_1 = \Order::find(123);
    }

    function it_tests_a_thing()
    {
        //(the method has access to the static class variable via
        //$this::$Order_1
    }
}