gpt4 book ai didi

php - 用具体值模拟 atLeastOnce,其余的不重要

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:39:11 24 4
gpt4 key购买 nike

问题在 PHP 中,但适用于使用 xUnit 框架的任何语言。

我想要一个 mock,需要 140 次调用 jump 方法。
我需要验证,至少一次有一个以 500 作为参数的调用。
我不在乎是否所有调用都是 500,但我至少需要一个调用了 500 的调用。

$mock = $this->getMock('Trampoline', ['jump']);

$mock->expects($this->atLeastOnce())
->method('jump')
->with($this->equalTo(500))
->will($this->returnValue(true));

$sportsman->setTramploine($mock);
$sportsman->jumpToRandomHeights($times = 140); // this calls Trampoline->jump
// I need to verify the sportsman had jumped
// to the height of 500 at least once out of the 140 jumps he is performing

在当前代码中,测试在第一次调用 jump 后失败,因为第一次调用的值不同于 500,这意味着 atLestOnce 这里只是表示应该调用该方法,而不是在其他调用中以特定值调用它。


解决方案

缺少的信息是在 with 中使用回调。感谢 edorian 在下面的回答,结果是这样的:

$testPassed = false;

$checkMinHeight = function ($arg) use(&$testPassed)
{
if($arg === 500)
$testPassed = true;

// return true for the mock object to consider the input valid
return true;
}


$mock = $this->getMock('Trampoline', ['jump'])
->expects($this->atLeastOnce())
->method('jump')
->with($checkMinHeight)
->will($this->returnValue(true));

$sportsman->setTramploine($mock);
$sportsman->jumpToRandomHeights($times = 1000); // this calls Trampoline->jump
// I need to verify the sportsman had jumped
// to the height of 500 at least once out of the 1000 jumps he is performing


$this->assertTrue($testPassed, "Sportsman was expected to
jump 500m at least once");

最佳答案

你可以,但我能想到的使用 PHPUnits 模拟 API 的最佳实现看起来仍然很令人毛骨悚然。

另一种更易读的解决方法是创建您自己的 Trampoline 子类并在那里实现它。

但对于挑战:

假设这个类:

<?php
class FancyMocking {
function doThing($value) { }
}

并且我们有 $x 调用,其中一个必须有 $value > 200:


<?php

class FancyMockingTest extends PHPUnit_Framework_TestCase {

public function testAtLeastOfMy200CallsShouldHaveAValueGreaterThan500() {
$maxInvocations = 200;

$mock = $this->getMock('FancyMocking');
$mock->expects($this->exactly($maxInvocations))
->method('doThing')
->with($this->callback(function ($value) use ($maxInvocations) {
static $invocationCount = 0;
static $maxValue = 0;

$maxValue = max($value, $maxValue);
/* The assertion function will be called twice by PHPUnit due to implementation details, so the *2 is a hack for now */
if (++$invocationCount == $maxInvocations * 2) {
$this->assertGreaterThan(200, $maxValue, 'in 500 tries the max value didn\'t to over 200');
}
return true;
}))
->will($this->returnCallback(function ($value) {
return $value >= 200;
}));
for($i = $maxInvocations - 2; $i; --$i) {
$mock->doThing(50);
}
var_dump($mock->doThing(250));
var_dump($mock->doThing(50));
}


}

这将产生:

PHPUnit 3.7.9 by Sebastian Bergmann.

.bool(true)
bool(false)


Time: 0 seconds, Memory: 2.75Mb

OK (1 test, 2 assertions)

意味着 250 的调用返回 true 并且整个测试用例有效。

如果失败:

为了让它失败,我们将 var_dump($mock->doThing(250)); 更改为 var_dump($mock->doThing(70)); 并运行再次:

PHPUnit 3.7.9 by Sebastian Bergmann.

Fbool(false)


Time: 0 seconds, Memory: 2.75Mb

There was 1 failure:

1) FancyMockingTest::testAtLeastOfMy200CallsShouldHaveAValueGreaterThan500
Expectation failed for method name is equal to <string:doThing> when invoked 200 time(s)
in 500 tries the max value didn't to over 200
Failed asserting that 70 is greater than 200.

.../FancyMockingTest.php:29

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

不使用 PHPUnits 模拟 API 的解决方案类似于

class FancyMockingFakeImplementation extends FancyMocking,使用它代替模拟并在那里编写自定义逻辑。

关于php - 用具体值模拟 atLeastOnce,其余的不重要,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13550914/

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