单元测试是否意味着必须嘲笑测试?

时间:2017-09-27 19:01:47

标签: php unit-testing phpunit integration-testing

单元测试是否意味着测试必须模拟,或单元测试的定义是否可以毫无嘲笑?

例如下面,这个测试是模拟的,所以它是单元测试:

/**
* @test
*/
public function it_should_return_true_if_ssh_client_is_connected()
{
    $this->phpSecLibShh->shouldReceive('isConnected')->andReturn(true)->once();

    $this->assertTrue($this->shell->connected($this->phpSecLibShh));
}

以下示例是单元测试还是集成测试?我不清楚这个:

/**
 * @test
 */
public function it_should_get_half_price_discount()
{
    $cost = 50;

    $order = new Order();

    // It does not connect to database or any other service
    $discounted = $order->discount(Order::DISCOUNT_HALF_PRICE, $cost);

    $this->assertEquals(25, $discounted);
}

2 个答案:

答案 0 :(得分:2)

模拟的主要思想是解除依赖性。单元测试不应该有任何依赖性。假设您的业务逻辑连接到数据库层,而数据库层又连接到数据库。现在,您正在编写单元测试来测试业务逻辑。如果您没有将数据库基础层与业务逻辑分离,那么您的单元测试将会进入数据库,这应该永远不会发生。所以你应该做的是将数据库依赖注入业务逻辑层,并在编写单元测试模拟那个依赖时。

长话短说,你不需要总是为单元测试模拟,但如果有任何依赖,那么应该嘲笑。如果您的测试有任何依赖性(比如数据库依赖性,文件依赖性等),那么您的测试不是单元测试而是集成测试

答案 1 :(得分:1)

Vijay,根据我的经验,团队将是决定他们是否需要单独/社交/适应性单元测试策略的最佳裁判,因为没有"一种尺寸适合所有解决方案"。

话虽如此,我相信适应性可能更实际。几乎所有中型到大型单片应用程序都将具有至少一个外部依赖性,这可能在开发/测试环境中不可用(例如:支付网关/决策引擎)。模拟数据将是我们唯一的选择。 然而,在相同的单元测试用例中,我们也可以使用另一个社交场景(通过在同一个类/命名空间中调用另一个函数)。甚至可能第二个函数具有单独的模拟测试用例。因此,它可以成为一种自适应单元测试策略,其中团队在他们所谓的单元方面采取集体立场,以及在场景基础上使用什么策略。 我们还应该记住,当我们开始构建部署管道时,我们的单元测试用例可以作为自动化过程的一部分来执行,该过程本身就是供应环境。因此,保持我们的单元测试用例与任何数据库/文件依赖关系隔离可能是有益的。

将来,当越来越多的应用程序进入微服务架构和容器化时,我们将更清楚地使用单元测试策略。开发/部署将在无状态和可独立部署/可管理的块中完成。像Docker Daemon API这样的工具可用于启动容纳特定相关/从属服务/功能的容器,并将其作为测试用例执行的一部分运行,这将阻止我们模拟其他服务,因为我们可以轻松激活一个装有相关服务的轻质容器并进行测试。