Я начинаю тестировать мир в Perl. Вот мой вопрос: у меня есть класс в Perl (я использую Moo BTW), и этот класс имеет 3 атрибута (я собираюсь поставить код ниже). Одним из этих атрибутов является массив, и он создается автоматически в конструкторе. Чтобы сгенерировать массив, мне нужно получить доступ к БД и выполнить один запрос.perl Test :: MockModule with DB acces
package Customer;
use 5.010;
use Data::Dumper;
use Moo;
use TT::SQL;
has id => (
is=>'ro',
required=>1,
);
has type => (
is=>'ro',
);
has emails => (
is=>'rw',
default => sub {
my ($self) = @_;
return $self->getEmails();
},
lazy=> 1,
);
sub getEmails
{
my $self=shift;
#obtaining the DB handler
my $db2 = $self->get_db_handler();
my $fmuser=$self->id;
my $type=$self->type;
my $query;
#checking the customer type to perform the query
if ($type eq "tshop")
{
$query="SELECT email from XXXXXXX WHERE XXXXX=? and XXXXXXXX=1 and XXXXXXX =1'";
}
else
{
$query="SELECT email from XXXXXXXX WHERE XXXXX=? and XXXXXXXX=1 and XXXXXXX =1";
}
my $ref = $db2->execute($query,$fmuser);
my @emails;
#retrieving emails
while (my $row = $ref->fetchrow_hashref ) {
@emails=(@emails,"$row->{email}\n");
}
return \@emails;
}
sub get_db_handler
{
my $user = "XXXXXXX";
my $password = 'XXXXXXX';
my $host = "XXXXX";
my $driver = "Pg";
my $timezone = "America/New_York";
my $dsn = "DBI:$driver:database=fm;host=$host";
my $db = DBI->connect($dsn,$user,$password) or die("Cannot connect to the DB !!");
return $db;
}
1;
Теперь я хочу запустить модульные тесты, чтобы проверить поведение предыдущего класса. До сих пор, я не буду использовать Test :: MockModule в следующем:
use diagnostics; # this gives you more debugging information
use warnings; # this warns you of bad practices
use strict; # this prevents silly errors
use Moo;
use Data::Dumper;
use Test::More tests => 2; # for the is() and isnt() functions
use Customer;
use FindBin qw/$RealBin/;
use Test::Deep;
use Test::MockModule;
use DBI;
my $dbh = DBI->connect("dbi:SQLite:dbname=$RealBin/test-cutomer.db","","") or die $DBI::errstr;
$dbh->do("
CREATE TABLE IF NOT EXISTS table (
id INTEGER PRIMARY KEY AUTOINCREMENT,
field1 INTEGER,
field2 INTEGER,
field3 TEXT,
field4 INTEGER,
field5 INTEGER
)
");
$dbh->do('
INSERT INTO table (field1,field2,field3,field4,field5) VALUES
(?,?,?,?,?)',undef,undef,92,'[email protected]',1,1
);
END {
unlink "$RealBin/test-customer.db";
}
{
my $mock = Test::MockModule->new("Customer");
$mock->mock("get_db_handler", sub { return $dbh });
my $customer=Customer->new(id=>92,type=>'other');
ok(defined $customer);
my $e=$customer->emails;
my @[email protected]$e;
my [email protected];
is($length,1, 'the emails are OK');
}
Я хочу издеваться метод get_db_handler для получения обработчика тест-CUSTOMER.DB и запускать запросы по этой локальной БД. До сих пор, я получаю следующее сообщение об ошибке:
1..2
ok 1
Can't locate object method "execute" via package "DBI::db" at Customer.pm line
46 (#1)
(F) You called a method correctly, and it correctly indicated a package
functioning as a class, but that package doesn't define that particular
method, nor does any of its base classes. See perlobj.
Uncaught exception from user code:
Can't locate object method "execute" via package "DBI::db" at Customer.pm line 46.
at Customer.pm line 46
Customer::getEmails('Customer=HASH(0x11359c8)') called at Customer.pm line 23
Customer::__ANON__('Customer=HASH(0x11359c8)') called at (eval 23) line 18
Customer::emails('Customer=HASH(0x11359c8)') called at t/stc.t line 66
# Looks like you planned 2 tests but ran 1.
# Looks like your test exited with 2 just after 1.
Скрипт работает нормально, я имею в виду, нет никаких проблем с кодом. Проблема заключается в том, что тест . Не могли бы вы взглянуть на это? Я по достоинству оценю это. Заранее спасибо.
Спасибо за быстрый ответ! Я работаю в этом примере. Но, можете ли вы объяснить немного больше о своем первом комментарии? – ccalderon911217
Если мне не нужно выбирать, то и другое! hahahaha Это будет классно для меня, если вы можете предоставить мне пример использования Test: MockModule, но в этом смысле я имею в виду насмешку над объектом, который обращается к БД в конструкторе. Большое спасибо!!! – ccalderon911217
Вы можете отправить сообщение на [codereview.se], если вы хотите получить полный анализ. Но пока вы хотите, чтобы клиент получал материал из какой-либо базы данных, я бы сделал свойство '$ dbh' с' has'. Таким образом, вы можете просто передать ему разные '$ dbh' в своих тестах и не нужно беспокоиться насчет насмешек. Если у вас есть несколько классов, которые нуждаются в dbh, превратите их в Moo :: Role.Но обратите внимание, что sqlite может не поддерживать все функции Postgres, поэтому есть некоторые подводные камни с использованием всего подхода sqlite. Вероятно, безопаснее использовать DBIx :: Class, и пусть это беспокоится об этом. – simbabque