单元测试 DB:: 在 Laravel 中使用 PhpUnit 调用
Unit testing DB:: call with PhpUnit in Laravel
我是 TDD 新手。我正在写一个小包,用数据库中的值插入一个字符串。到目前为止,我设法编写了大部分测试,但现在我陷入困境,因为我需要测试对数据库的调用。
我想测试一个 class,它在给定 table、列和 ID 的情况下检索数据库中的特定行。然后它应该 return 该实例列值。
class DatabaseResolver
{
private $referredField;
private $dependencies;
public function __construct(ReferredField $referredField, array $dependencies)
{
$this->referredField = $referredField;
$this->dependencies = $dependencies;
}
public function resolve() : string
{
if(!isset($this->dependencies['id'])) {
throw new MissingDependencyException('id');
}
$instance = $this->getTargetedInstance();
if ($instance) {
return $instance->{$this->referredField->column};
}
return '';
}
public function getTargetedInstance()
{
return DB::table($this->referredField->table)
->select($this->referredField->column)
->where('id', $this->dependencies['id'])
->first();
}
}
我已经设法测试它在依赖数组中没有 id 时抛出我的异常,并且当找不到标记时它 return 是原始句子:
/** @test */
public function it_will_throw_if_no_id_is_present_in_dependency()
{
$this->expectException(MissingDependencyException::class);
$rf = ReferredField::newFactory()->testAsTable()->create();
$rf->getReferredValue([]);
}
/** @test */
public function it_returns_blanked_tokens_when_referred_field_is_not_found()
{
$stringToInterpolate = 'This is a {{adj}} day!';
$interpolatedString = $this->interpoler->interpolate($stringToInterpolate, ['adj' => ['id' => -1]]);
$this->assertEquals('This is a day!', $interpolatedString);
}
编辑:
这是内插器的代码 class:
<?php
namespace Armcanada\LaravelReferredField\Concerns;
use Armcanada\LaravelReferredField\Exceptions\MissingDependencyException;
class Interpoler
{
private $tokenizer;
private $mapper;
public function __construct(Tokenizer $tokenizer = null, TokenReferredFieldMapper $mapper = null)
{
$this->tokenizer = $tokenizer ?: new Tokenizer;
$this->mapper = $mapper ?: new TokenReferredFieldMapper;
}
public function interpolate(string $text, array $dependencies = []) : string
{
$map = $this->getReferredFieldsFromText($text);
$replacedMap = $map->mapWithKeys(function($referredField, $token) use($dependencies) {
if (!isset($dependencies[$token])) {
throw new MissingDependencyException($token);
}
$key = str_replace(' ', $token, config('laravel-referred-field.interpolation_pattern'));
return [$key => $referredField?->getReferredValue($dependencies[$token]) ?? null];
});
$replacedMap->map(function($newValue, $token) use(&$text) {
$text = str_replace($token, $newValue, $text);
});
return $text;
}
public function getReferredFieldsFromText($text)
{
$tokens = $this->tokenizer->extract($text);
return $this->mapper->mapTokensToReferredFields($tokens);
}
}
我的 ReferredField 模型:
<?php
namespace Armcanada\LaravelReferredField\Models;
use Armcanada\LaravelReferredField\Database\Factories\ReferredFieldFactory;
use Armcanada\LaravelReferredField\Resolvers\DatabaseResolver;
use Armcanada\LaravelReferredField\Traits\Referrable;
use Illuminate\Database\Eloquent\Model;
class ReferredField extends Model
{
use Referrable;
protected $guarded = [];
protected $table = 'referred_fields';
protected static function newFactory()
{
return ReferredFieldFactory::new();
}
public function getReferredValue(array $dependencies) : string
{
$resolver = $this->getResolver($dependencies);
return $resolver->resolve();
}
private function getResolver($dependencies)
{
if ($this->table !== null) {
return new DatabaseResolver($this, $dependencies);
}
//return new HandlerResolver($this, $dependencies);
}
}
如何测试这条路径?
$instance = $this->getTargetedInstance();
if ($instance) {
return $instance->{$this->referredField->field};
}
我不完全确定我理解你的代码,但如果你想测试 $instance
不为空的路径,你可以部分模拟 DatabaseResolver
的 getTargetedInstance
方法。
public function test_insert_test_method_name_here()
{
$rf = ReferredField::factory()->create();
$this->partialMock(DatabaseResolver::class)
->shouldReceive('getTargetedInstance')
->andReturn((object) [$rf->column => 'nice']);
$stringToInterpolate = 'This is a {{ adj }} day!';
$interpolatedString = $this->interpoler->interpolate($stringToInterpolate, ['adj' => ['id' => -1]]);
$this->assertEquals('This is a nice day!', $interpolatedString);
}
我是 TDD 新手。我正在写一个小包,用数据库中的值插入一个字符串。到目前为止,我设法编写了大部分测试,但现在我陷入困境,因为我需要测试对数据库的调用。 我想测试一个 class,它在给定 table、列和 ID 的情况下检索数据库中的特定行。然后它应该 return 该实例列值。
class DatabaseResolver
{
private $referredField;
private $dependencies;
public function __construct(ReferredField $referredField, array $dependencies)
{
$this->referredField = $referredField;
$this->dependencies = $dependencies;
}
public function resolve() : string
{
if(!isset($this->dependencies['id'])) {
throw new MissingDependencyException('id');
}
$instance = $this->getTargetedInstance();
if ($instance) {
return $instance->{$this->referredField->column};
}
return '';
}
public function getTargetedInstance()
{
return DB::table($this->referredField->table)
->select($this->referredField->column)
->where('id', $this->dependencies['id'])
->first();
}
}
我已经设法测试它在依赖数组中没有 id 时抛出我的异常,并且当找不到标记时它 return 是原始句子:
/** @test */
public function it_will_throw_if_no_id_is_present_in_dependency()
{
$this->expectException(MissingDependencyException::class);
$rf = ReferredField::newFactory()->testAsTable()->create();
$rf->getReferredValue([]);
}
/** @test */
public function it_returns_blanked_tokens_when_referred_field_is_not_found()
{
$stringToInterpolate = 'This is a {{adj}} day!';
$interpolatedString = $this->interpoler->interpolate($stringToInterpolate, ['adj' => ['id' => -1]]);
$this->assertEquals('This is a day!', $interpolatedString);
}
编辑: 这是内插器的代码 class:
<?php
namespace Armcanada\LaravelReferredField\Concerns;
use Armcanada\LaravelReferredField\Exceptions\MissingDependencyException;
class Interpoler
{
private $tokenizer;
private $mapper;
public function __construct(Tokenizer $tokenizer = null, TokenReferredFieldMapper $mapper = null)
{
$this->tokenizer = $tokenizer ?: new Tokenizer;
$this->mapper = $mapper ?: new TokenReferredFieldMapper;
}
public function interpolate(string $text, array $dependencies = []) : string
{
$map = $this->getReferredFieldsFromText($text);
$replacedMap = $map->mapWithKeys(function($referredField, $token) use($dependencies) {
if (!isset($dependencies[$token])) {
throw new MissingDependencyException($token);
}
$key = str_replace(' ', $token, config('laravel-referred-field.interpolation_pattern'));
return [$key => $referredField?->getReferredValue($dependencies[$token]) ?? null];
});
$replacedMap->map(function($newValue, $token) use(&$text) {
$text = str_replace($token, $newValue, $text);
});
return $text;
}
public function getReferredFieldsFromText($text)
{
$tokens = $this->tokenizer->extract($text);
return $this->mapper->mapTokensToReferredFields($tokens);
}
}
我的 ReferredField 模型:
<?php
namespace Armcanada\LaravelReferredField\Models;
use Armcanada\LaravelReferredField\Database\Factories\ReferredFieldFactory;
use Armcanada\LaravelReferredField\Resolvers\DatabaseResolver;
use Armcanada\LaravelReferredField\Traits\Referrable;
use Illuminate\Database\Eloquent\Model;
class ReferredField extends Model
{
use Referrable;
protected $guarded = [];
protected $table = 'referred_fields';
protected static function newFactory()
{
return ReferredFieldFactory::new();
}
public function getReferredValue(array $dependencies) : string
{
$resolver = $this->getResolver($dependencies);
return $resolver->resolve();
}
private function getResolver($dependencies)
{
if ($this->table !== null) {
return new DatabaseResolver($this, $dependencies);
}
//return new HandlerResolver($this, $dependencies);
}
}
如何测试这条路径?
$instance = $this->getTargetedInstance();
if ($instance) {
return $instance->{$this->referredField->field};
}
我不完全确定我理解你的代码,但如果你想测试 $instance
不为空的路径,你可以部分模拟 DatabaseResolver
的 getTargetedInstance
方法。
public function test_insert_test_method_name_here()
{
$rf = ReferredField::factory()->create();
$this->partialMock(DatabaseResolver::class)
->shouldReceive('getTargetedInstance')
->andReturn((object) [$rf->column => 'nice']);
$stringToInterpolate = 'This is a {{ adj }} day!';
$interpolatedString = $this->interpoler->interpolate($stringToInterpolate, ['adj' => ['id' => -1]]);
$this->assertEquals('This is a nice day!', $interpolatedString);
}