【问题标题】:How to Str::shouldReceive? (mocking Illuminate\Support\Str)如何Str::shouldReceive? (嘲笑 Illuminate\Support\Str)
【发布时间】:2014-08-19 16:59:18
【问题描述】:

我有一个使用 Str::random() 的课程,我想对其进行测试。

但是当我在测试中使用Str::shouldReceive('random') 时,我得到一个 BadMethodCallException 说方法 shouldReceive 不存在。

我也尝试直接模拟该类并将其绑定到 IOC,但它继续执行原始类,生成一个随机字符串而不是我在模拟上设置的返回值。

    $stringHelper = Mockery::mock('Illuminate\Support\Str');
    $this->app->instance('Illuminate\Support\Str', $stringHelper);
    //$this->app->instance('Str', $stringHelper);

    $stringHelper->shouldReceive('random')->once()->andReturn('some password');
    //Str::shouldReceive('random')->once()->andReturn('some password');

【问题讨论】:

    标签: unit-testing laravel facade mockery


    【解决方案1】:

    您将无法以这种方式模拟 Illuminate\Support\Str(请参阅 mockery docs。这就是我要测试它的方式。

    在尝试生成随机字符串的类中,您可以创建一个生成随机字符串的方法,然后在测试中覆盖该方法(代码未实际测试):

        // class under test
        class Foo {
            public function __construct($otherClass) {
                $this->otherClass = $otherClass;
            }
    
            public function doSomethingWithRandomString() {
                $random = $this->getRandomString();
                $this->otherClass->useRandomString($random);
            }
    
            protected function getRandomString() {
                return \Illuminate\Support\Str::random();
            }
        }
    
        // test file
        class FooTest {
            protected function fakeFooWithOtherClass() {
                $fakeOtherClass = Mockery::mock('OtherClass');
                $fakeFoo = new FakeFoo($fakeOtherClass);
                return array($fakeFoo, $fakeOtherClass);
            }
    
            function test_doSomethingWithRandomString_callsGetRandomString() {
                 list($foo) = $this->fakeFooWithOtherClass();
                 $foo->doSomethingWithRandomString();
    
                 $this->assertEquals(1, $foo->getRandomStringCallCount);
            }
    
            function test_doSomethingWithRandomString_callsUseRandomStringOnOtherClassWithResultOfGetRandomString() {
                list($foo, $otherClass) = $this->fakeFooWithOtherClass();
    
                $otherClass->shouldReceive('useRandomString')->once()->with('fake random');
                $foo->doSomethingWithRandomString();
            }
        }
        class FakeFoo extends Foo {
            public $getRandomStringCallCount = 0;
            protected function getRandomString() {
                $this->getRandomStringCallCount ++;
                return 'fake random';
            }
        }
    

    【讨论】:

      【解决方案2】:

      你不能使用 laravel Mock 因为 Str::random() 不是 Facade。 相反,您可以使用设置测试环境的方法创建一个新类。像这样: ‍‍‍

      <?php
      
      namespace App;
      
      
      use Illuminate\Support\Str;
      
      class Token
      {
          static $testToken =null;
          public static function generate(){
              return static::$testToken ?:Str::random(60);
          }
      
          public static function setTest($string){
              static::$testToken = $string;
          }
      }

      【讨论】:

        【解决方案3】:

        只要您还使用 IoC 来解决该类的绑定,您尝试的方法就会起作用。

        $instance = resolve(\Illuminate\Support\Str::class);
        $instance::random();
        

        【讨论】:

          猜你喜欢
          • 2021-08-30
          • 2022-06-14
          • 2015-05-30
          • 2016-02-24
          • 2011-04-10
          • 1970-01-01
          • 2014-10-27
          • 2016-10-02
          相关资源
          最近更新 更多