想测试 laravel 中工厂创建的特定方法的调用
Posted
技术标签:
【中文标题】想测试 laravel 中工厂创建的特定方法的调用【英文标题】:Want to test the calling of a specific method created by a factory in laravel 【发布时间】:2021-11-04 06:09:04 【问题描述】:我正在尝试编写一个执行类似操作的集成测试。
使用ModelClass::factory([$params])
而不是构造函数在测试的setUp方法中创建类的实例
在这个类上调用一些导致各种事情发生的方法
事件会在某个时候被触发
监听事件,事件监听器将调用产生事件的同一对象的方法。
具体调用哪个方法(和参数)取决于类内部的一些逻辑(这主要是我要测试的)。
方法本身没有做任何事情(目前),但我想知道它被调用了。功能可能会在未来某个时候由其他人实现。
所以我想断言这个方法在测试过程中的某个时间点被调用,并测试哪些参数被传递给它。目前我已经设法模拟出事件本身以检查它是否被触发,但我只能测试该方法是否被手动调用(通过将dd()
放入其中)。如果不模拟整个对象,我似乎无法找到一种方法来做到这一点(这会破坏测试的目的,因为那时我只是在测试模拟)。
我知道你可以做“partial”模拟,也许这就是我需要的,但这似乎不适用于::factory([$params])
构造函数风格。
我将此作为答案包含在内,因为我无法编辑我的原件。
<?php
// The test itself
protected function setUp() : void
parent::setUp();
$this->item = Item::factory()->createOne([
"name" => "testing name",
// Some other attributes
]);
public function test_the_thing() : void
$this->item->doSomeWork();
$this->assertShouldHaveBeenCalled($item, "someMethod") // I want something like this
// Then a trait attached to the item class that looks like this
public static function bootItemTrait(): void
Event::listen(function(MyCustomEvent $event)
if(method_exists($event->item,"someMethod") && some_other_conditions())
$event->item->someMethod();
);
public function doSomeWork() : void
$result = doSomeComplicatedThings()
MyCustomEvent::dispatch($this,$result);
// My custom event is just a basic event with this constructor
public function __construct($item, $result)
$this->result = $result;
$this->item = $item;
【问题讨论】:
您需要包含一些样板代码或制作的示例,以便我们有一些代码来重现您的问题。毫无疑问这是可能的:) 我刚刚添加了一些示例代码,它们是我正在尝试做的简化版本。 【参考方案1】:欢迎来到嘲讽的欢乐世界,愿我做你的向导。您想模拟调用并从那里获取,问题是依赖注入和模拟Laravel
模型并不容易,不推荐。
为了解决这个问题,请为您的调用创建一个包装器类,这将允许您覆盖 Laravel
容器中的包装器。所以你在哪里->doWork();
。你可以做类似的事情。重要的是要知道,在使用依赖注入时,永远不要使用关键字new
。而是使用app(YourClass::class);
、resolve(YourClass::class);
或使用构造函数/句柄注入。在这种情况下,我使用resolve()
方法。
class YourModel extends Model
public function doWork()
/** @var DoWorkService $doWorkService */
$doWorkService = resolve(DoWorkService::class);
$doWorkService->doWork(1, "2");
在这个构思的例子中,我做了一个空壳来证明这一点。
namespace App\Services;
class DoWorkService
public function doWork($param1, $param2)
throw new \Exception('This is mocked and should not be called');
现在在您的测试课程中,您可以使用 Laravel
提供的 Mocking 助手。此示例需要调用一次doWork()
方法,参数为1, "2"
,在这种情况下返回true
。
namespace Tests\Unit;
use App\Services\DoWorkService;
use Mockery\MockInterface;
use Tests\TestCase;
class DoWorkTest extends TestCase
public function testDoWork()
$yourModel = // create your model with the factory;
$mock = $this->mock(DoWorkService::class, function (MockInterface $mock)
$mock->shouldReceive('doWork')
->once()
->with(1, "2")
->andReturn(true);
);
$yourModel->doWork();
这是在我的本地项目上测试的,所以你应该设置为实现类似的东西。
【讨论】:
以上是关于想测试 laravel 中工厂创建的特定方法的调用的主要内容,如果未能解决你的问题,请参考以下文章