gpt4 book ai didi

php - 集成测试模拟外观与注入(inject)模拟

转载 作者:IT王子 更新时间:2023-10-28 23:55:15 25 4
gpt4 key购买 nike

我们有一些遗留的 Laravel 项目在类中使用外观。

use Cache;

LegacyClass
{
public function cacheFunctionOne()
{
$result = Cache::someFunction('parameter');

// logic to manipulate result

return $result;
}

public function cacheFunctionTwo()
{
$result = Cache::someFunction('parameter');

// different logic to manipulate result

return $result;
}
}

我们最近的项目使用外观表示的底层 Laravel 类的依赖注入(inject) hinted at by Taylor Otwell himself . (我们对每个类都使用构造函数注入(inject),但为了使示例简短,这里我使用方法注入(inject)并使用单个类。)

use Illuminate\Cache\Repository as Cache;

ModernClass
{
public function cacheFunctionOne(Cache $cache)
{
$result = $cache->someFunction('parameter');

// logic to manipulate result

return $result;
}

public function cacheFunctionTwo(Cache $cache)
{
$result = $cache->someFunction('parameter');

// different logic to manipulate result

return $result;
}
}

我知道立面 can be mocked

public function testExample()
{
Cache::shouldReceive('get')
->once()
->with('key')
->andReturn('value');

$this->visit('/users')->see('value');
}

这非常适合单元测试。我试图了解的问题是,这些外墙是否在“全局范围内”被 mock 。

例如,假设我正在编写一个集成测试(在模拟服务的同时测试一些相互关联的类——而不是使用实时服务的端到端测试),它在某个时候执行两个单独的类,它们包含相同的使用相同参数调用相同方法的外观

在被调用的这些类之间,有一些复杂的功能可以更改使用相同参数的 facades 方法返回的数据。*

$modernClass->cacheFunctionOne($cache); // easily mocked

// logic that changes data returned by laravel Cache object function 'someFunction'

$modernClass->cacheFunctionTwo($cache); // easily mocked with a different mock

我们的现代类很容易测试,因为外观代表的底层类被注入(inject)到每个类(在这个例子中,每个方法)。这意味着我可以创建两个单独的模拟并将它们注入(inject)每个类(方法)以模拟不同的结果。

$legacyClass->cacheFunctionOne();

// logic that changes data returned by laravel Cache object function 'someFunction'

$legacyClass->cacheFunctionTwo();

虽然在遗留系统中,模拟外观似乎是“全局”的,因此当外观在每个类中运行时,返回完全相同的值.

我这样想对吗?

*我理解这个示例从代码架构和测试的角度来看可能看起来完全多余,但我正在剥离所有实际功能以尝试提供某种“简单”示例来说明我的要求。

最佳答案

依赖注入(inject)与 Facades

依赖注入(inject)的主要好处之一是,一旦您开始将依赖注入(inject)方法而不是在方法中实例化/硬编码它们,代码就会变得更易于测试。这是因为您可以从单元测试内部传递依赖项,它们将通过代码传播。

参见:http://slashnode.com/dependency-injection/

依赖注入(inject)与门面形成鲜明对比。 Facades 是静态全局类,PHP 语言不允许在静态类上覆盖或替换静态函数。 Laravel facades 使用 Mockery 来提供模拟功能,并且它们受到与上述相同的事实的限制。

集成测试的问题可能出现在您希望从非模拟缓存中检索数据的地方,但是一旦您使用 Facade::shouldReceive(),那么 Facade::get() 将被模拟缓存覆盖。反之亦然。因此,Facades 不适合交错调用模拟数据和非模拟数据的地方。

为了使用您需要的不同数据集测试您的代码,最佳做法是重构您的遗留代码以使用 DI。

集成测试

更简单的方法

另一种方法是在集成测试开始时调用多个带有期望的 Facade::shouldReceive()。确保您在集成测试中进行的每个调用都以正确的顺序获得正确数量的期望。鉴于您现有的代码库,这可能是编写测试的更快方法。

更难的方法

虽然依赖注入(inject)是编程的最佳实践。很可能是因为您的代码库中有太多遗留类,以至于重构需要花费令人难以置信的时间。在这种情况下,可能值得考虑使用带有固定装置的测试数据库进行端到端集成测试。

附录:

关于php - 集成测试模拟外观与注入(inject)模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39255103/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com