- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我们有一些遗留的 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)是编程的最佳实践。很可能是因为您的代码库中有太多遗留类,以至于重构需要花费令人难以置信的时间。在这种情况下,可能值得考虑使用带有固定装置的测试数据库进行端到端集成测试。
附录:
fhinkel 于 2015 年 2 月 6 日评论
:https://github.com/padraic/mockery/issues/401 关于php - 集成测试模拟外观与注入(inject)模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39255103/
我正在尝试测试依赖于其他服务 authService 的服务 documentViewer angular .module('someModule') .service('docu
如果我的网站上线(不要认为它会,目前它只是一个学习练习)。 我一直在使用 mysql_real_escape_string();来自 POST、SERVER 和 GET 的数据。另外,我一直在使用 i
我有以下代码,它容易受到 SQL 注入(inject)的攻击(我认为?): $IDquery = mysqli_query($connection, "SELECT `ID` FROM users W
我一直在自学如何创建扩展,以期将它们用于 CSS 注入(inject)(以及最终以 CSS 为载体的 SVG 注入(inject),但那是以后的问题)。 这是我当前的代码: list .json {
这个简单的代码应该通过 Java Spring 实现一个简单的工厂。然而结果是空指针,因为 Human 对象没有被注入(inject)对象(所以它保持空)。 我做错了什么? 谢谢 配置 @Config
我正在编写一个 ASP.NET MVC4 应用程序,它最终会动态构建一个 SQL SELECT 语句,以便稍后存储和执行。动态 SQL 的结构由用户配置以用户友好的方式确定,具有标准复选框、下拉列表和
首先让我说我是我为确保 SQL 注入(inject)攻击失败而采取的措施的知己。所有 SQL 查询值都是通过事件记录准备语句完成的,所有运算符(如果不是硬编码)都是通过数字白名单系统完成的。这意味着如
这是 SQL 映射声称可注入(inject)的负载: user=-5305' UNION ALL SELECT NULL,CONCAT(0x716b6b7071,0x4f5577454f76734
我正在使用 Kotlin 和 Android 架构组件(ViewModel、LiveData)构建一个新的 Android 应用程序的架构,并且我还使用 Koin 作为我的依赖注入(inject)提供
假设 RequestScope 处于 Activity 状态(使用 cdi-unit 的 @InRequestScope) 给定 package at.joma.stackoverflow.cdi;
我有一个搜索表单,可以在不同的提供商中搜索。 我从拥有一个基本 Controller 开始 public SearchController : Controller { protected r
SQLite 注入 如果您的站点允许用户通过网页输入,并将输入内容插入到 SQLite 数据库中,这个时候您就面临着一个被称为 SQL 注入的安全问题。本章节将向您讲解如何防止这种情况的发生,确保脚
我可以从什么 dll 中获得 Intercept 的扩展?我从 http://github.com/danielmarbach/ninject.extensions.interception 添加了
使用 NInject 解析具有多个构造函数的类似乎不起作用。 public class Class1 : IClass { public Class1(int param) {...} public
我有一个 MetaManager 类: @Injectable() export class MetaManager{ constructor(private handlers:Handler
我是 Angular 的新手,我不太清楚依赖注入(inject)是如何工作的。我的问题是我有依赖于服务 B 的服务 A,但是当我将服务 A 注入(inject)我的测试服务 B 时,服务 B 变得未定
我正在为我的项目使用 android 应用程序启动、刀柄和空间。我在尝试排队工作时遇到错误: com.test E/WM-WorkerFactory: Could not instantiate co
我不确定这是什么糖语法,但让我向您展示问题所在。 def factors num (1..num).select {|n| num % n == 0} end def mutual_factors
简单的问题,我已经看过这个了:Managing imports in Scalaz7 ,但我不知道如何最小化注入(inject) right和 left方法到我的对象中以构造 \/ 的实例. 我确实尝
在我的 Aurelia SPA 中,我有一些我想在不同模块中使用的功能。它依赖于调用时给出的参数和单例的参数。有没有办法创建一个导出函数,我可以将我的 Auth 单例注入(inject)其中,而不必在
我是一名优秀的程序员,十分优秀!