单元测试是否意味着必须模拟测试?
Does Unit Test mean that the test has to be mocked?
单元测试是否意味着测试必须 mocked 或单元测试的定义可以不被 mock ?
例如下面这个测试是模拟的,所以它是单元测试:
/**
* @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);
}
模拟的主要思想是解耦依赖。单元测试不应该有任何依赖。假设您的业务逻辑连接到数据库层,而数据库层又连接到数据库。现在您正在编写单元测试来测试您的业务逻辑。如果您没有将数据库基础层与业务逻辑分离,那么您的单元测试将去访问数据库,这永远不会发生。所以你应该做的是将数据库依赖注入业务逻辑层,并在编写单元测试时模拟该依赖。
长话短说,单元测试并不总是需要模拟,但如果有任何依赖性,则应该模拟。如果你的测试有任何依赖(比如数据库依赖、文件依赖等)那么你的测试不是单元测试而是集成测试
Vijay,根据我的经验,团队将是决定他们是否需要 solitary/social/adaptive 单元测试策略的最佳法官,因为没有 "One size fits all solution"。
话虽如此,我认为适应性可能更实用。几乎所有大中型单体应用程序都至少有一个外部依赖项,这在 development/test 环境中可能不可用(例如:支付网关/决策引擎)。模拟数据将是我们唯一的选择。
然而,在同一个单元测试用例中,我们也可以加入另一个社交场景(通过在同一个 class/namespace 中调用另一个函数)。第二个函数甚至可能有单独的模拟测试用例。因此,它可以成为一种自适应单元测试策略,其中团队在他们所谓的单元以及在逐个场景的基础上使用什么策略方面采取集体立场。
我们还应该记住,当我们开始构建部署管道时,我们的单元测试用例可以作为自动化过程的一部分执行,该过程本身就是在配置环境。因此,将我们的单元测试用例与任何 database/file 依赖项隔离开来可能是有益的。
将来,当越来越多的应用程序转向微服务架构和容器化时,我们将更加清楚要使用的单元测试策略。开发/部署将在无状态和独立 deployable/manageable 块中完成。 Docker Daemon API 等工具可用于启动一个容器,该容器承载特定的 related/dependent service/functionality 和 运行 它作为我们测试用例执行的一部分,这将阻止我们不必模拟其他服务,因为我们可以轻松地激活具有相关服务的轻量级容器并对其进行测试。
单元测试是否意味着测试必须 mocked 或单元测试的定义可以不被 mock ?
例如下面这个测试是模拟的,所以它是单元测试:
/**
* @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);
}
模拟的主要思想是解耦依赖。单元测试不应该有任何依赖。假设您的业务逻辑连接到数据库层,而数据库层又连接到数据库。现在您正在编写单元测试来测试您的业务逻辑。如果您没有将数据库基础层与业务逻辑分离,那么您的单元测试将去访问数据库,这永远不会发生。所以你应该做的是将数据库依赖注入业务逻辑层,并在编写单元测试时模拟该依赖。
长话短说,单元测试并不总是需要模拟,但如果有任何依赖性,则应该模拟。如果你的测试有任何依赖(比如数据库依赖、文件依赖等)那么你的测试不是单元测试而是集成测试
Vijay,根据我的经验,团队将是决定他们是否需要 solitary/social/adaptive 单元测试策略的最佳法官,因为没有 "One size fits all solution"。
话虽如此,我认为适应性可能更实用。几乎所有大中型单体应用程序都至少有一个外部依赖项,这在 development/test 环境中可能不可用(例如:支付网关/决策引擎)。模拟数据将是我们唯一的选择。 然而,在同一个单元测试用例中,我们也可以加入另一个社交场景(通过在同一个 class/namespace 中调用另一个函数)。第二个函数甚至可能有单独的模拟测试用例。因此,它可以成为一种自适应单元测试策略,其中团队在他们所谓的单元以及在逐个场景的基础上使用什么策略方面采取集体立场。 我们还应该记住,当我们开始构建部署管道时,我们的单元测试用例可以作为自动化过程的一部分执行,该过程本身就是在配置环境。因此,将我们的单元测试用例与任何 database/file 依赖项隔离开来可能是有益的。
将来,当越来越多的应用程序转向微服务架构和容器化时,我们将更加清楚要使用的单元测试策略。开发/部署将在无状态和独立 deployable/manageable 块中完成。 Docker Daemon API 等工具可用于启动一个容器,该容器承载特定的 related/dependent service/functionality 和 运行 它作为我们测试用例执行的一部分,这将阻止我们不必模拟其他服务,因为我们可以轻松地激活具有相关服务的轻量级容器并对其进行测试。