Ich beginne in der Unit Testing Welt in Perl. Hier ist meine Frage: Ich habe eine Klasse in Perl (ich benutze Moo BTW) und diese Klasse hat 3 Attribute (ich werde den Code unten setzen). Eines dieser Attribute ist ein Array und wird automatisch im Konstruktor generiert. Um das Array zu generieren, muss ich auf eine Datenbank zugreifen und eine Abfrage ausführen.perl Test :: MockModule mit DB-Zugang
Jetzt möchte ich Unit-Tests ausführen, um das Verhalten der vorherigen Klasse zu überprüfen. Bis jetzt bin ich mit Test :: MockModule als nächstes:
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');
}
Ich möchte die get_db_handler Methode verspotten den Test-Customer.db Handler abzurufen und die Abfragen über diese lokale DB zu laufen. Bisher habe ich die folgende Fehlermeldung erhalten:
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.
Das Skript läuft OK, ich meine, gibt es kein Problem mit dem Code. Das Problem ist mit dem Test. Könnten Sie sich das bitte ansehen? Ich werde es sehr schätzen. Danke im Voraus.
Danke für die schnelle Antwort! Ich arbeite im Beispiel. Aber kannst du ein bisschen mehr über deinen ersten Kommentar erzählen? – ccalderon911217
Wenn ich nicht wählen muss, beides! hahahaha Es wird großartig für mich sein, wenn du mir ein Beispiel für die Verwendung von Test: MockModule liefern kannst, aber auf diese Weise meine ich, ein Objekt zu verspotten, das im Konstruktor auf die DB zugreift. Vielen Dank!!! – ccalderon911217
Sie können [codereview.se] posten, wenn Sie eine vollständige Analyse wünschen. Aber jetzt, wenn Sie wollen, dass der Kunde Sachen aus einer Datenbank bekommt, würde ich die '$ dbh' eine Eigenschaft mit' has' machen. Auf diese Weise können Sie einfach einen anderen '$ dbh' in Ihren Tests übergeben und müssen sich nicht um Spott kümmern. Wenn Sie mehrere Klassen haben, die eine dbh benötigen, verwandeln Sie sie in eine Moo :: Role.Aber achten Sie darauf, dass sqlite nicht alle Funktionen von Postgres unterstützt, es gibt also einige Fallstricke mit dem ganzen SQLite-Ansatz. Es ist wahrscheinlich sicherer, DBIx :: Class zu verwenden und sich darum zu kümmern. – simbabque