【问题标题】:Is it possible to mock "require" or "require_once" statement with Kahlan?是否可以用 Kahlan 模拟“require”或“require_once”语句?
【发布时间】:2025-12-22 03:10:06
【问题描述】:

我有非常旧的遗留代码。在开始重构之前,我想对代码进行一些单元测试。但不好的是文件通过“require_once”语句相互依赖(但是,我要测试的函数是隔离的)。

所以如果我无法模拟“require_once”语句,我就无法编写正常的测试。

我正在使用 Kahlan 框架进行测试。那么可以模拟这样的陈述吗?如果是,比如何?

【问题讨论】:

  • 因为require_once 是一个PHP 语句,所以它介于非常难以模拟和不可能模拟之间。但是,除非执行了一些不需要的代码,否则简单地包含彼此的文件不一定会破坏单元测试,不是吗?
  • @deceze 我知道 Kahlan 允许以特定方式进行猴子修补(例如,用于内置函数):它复制文件,用他自己的代码替换此代码中的一些内置函数,然后对这个“新”代码执行测试。这种方法也可用于模拟“require_once”或任何其他语句,因此问题诞生了。而且,不幸的是,一些必需的文件会执行不需要的辅助代码。
  • @deceze 我解决了这个问题。有兴趣的可以看我的回答。
  • 你需要的是功能测试,而不是单元测试。
  • @mike 我也需要它们,但是功能测试非常缓慢且难以编写。

标签: php unit-testing


【解决方案1】:

这是不可能的。

但是,我为 Kahlan 制作了一个插件,允许从任何文件中“提取”函数并跳过所有其他代码。它不允许完全“模拟”语句,但它允许测试孤立的函数。我提出了 pull-request,如果它不被接受,我将制作一个单独的 packagegist composer 数据包并更新此答案。

可在此处找到更改:

https://github.com/lamp-of-god/kahlan/tree/isolator-plugin

使用示例:

文件:

<?php
require_once 'something';  // This string will be "skipped" on test

do_something();  // This string too

function test()
{
    return 42;
}

用插件测试这个文件:

<?php

use Kahlan\Plugin\Isolator;

Isolator::isolate(dirname(__DIR__).'/../test.php');

describe('test()', function() {
    it('returns 42', function() {
        expect(test())->toBe(42);
    });
});

【讨论】:

    最近更新 更多