I am coding a test, but I get some unexpected results in basic relationships. I use in memory sqlite db.
Those test were working well with MySQL db. I guess it has something to do with this migration.
$tournament0 = factory(Tournament::class)
->create(['user_id' => $this->simpleUser->id]);
$this->simpleUser is created on setUp() method
Now, when $this->simpleUser->tournaments should return $tournament0, but it is empty.
My relationship is working, it is not broken. Also, when testing manually in the browser, it works.
It just fail when using phpunit...
Here is the setUp() Method:
public function setUp()
{
parent::setUp();
$this->simpleUser = factory(User::class)->create(['role_id' => Config::get('constants.ROLE_USER')]);
}
Full method that is failing:
/** #test */
public function dashboard_check_initial_state()
{
Artisan::call('db:seed', ['--class' => 'CountriesSeeder', '--database' => 'sqlite']);
Artisan::call('db:seed', ['--class' => 'TournamentLevelSeeder', '--database' => 'sqlite']);
Artisan::call('db:seed', ['--class' => 'CategorySeeder', '--database' => 'sqlite']);
// Given
$this->logWithUser($this->simpleUser);
// Nothing has been created, default dash
$this->visit('/')
->see(trans('core.create_new_tournament'))
->dontSee(trans('core.congigure_categories'));
// Create 1 tournament
$tournament0 = factory(Tournament::class)->create(['user_id' => $this->simpleUser->id]);
$this->visit('/')
->seeInElement("p.text-muted", trans('core.no_tournament_created_yet'));
// Now configure 2/2 categories
$championship1 = factory(Championship::class)->create(['tournament_id' => $tournament0->id,'category_id'=>1]);
$championship2 = factory(Championship::class)->create(['tournament_id' => $tournament0->id,'category_id'=>2]);
factory(ChampionshipSettings::class)->create(['championship_id' => $championship1->id]);
factory(ChampionshipSettings::class)->create(['championship_id' => $championship2->id]);
$this->visit('/')
->seeInElement("span.text-muted", trans('core.congigure_categories'));
}
Any idea what can it be?
Related
I create a factory of a model inside an artisan command:
public function handle()
{
if (!$this->isDevelopment()) {
$this->errorMessageSwitchEnvToDev();
return;
}
$userId = $this->ask('Please specifiy user_id you want to add the payouts to.',2148);
$numberOfPayouts = $this->ask('How many payouts you want to generate?', 10);
factory(\App\Payout::class, $numberOfPayouts)->create([
'user_id' => $userId,
]);
}
The artisan works on my local desktop, but it does not work after deployment on my test server.
I get the following error message:
InvalidArgumentException : Unable to locate factory with name [100] [App\Payout].
at /www/htdocs/w0146a6f/dev/dev4.partner.healyworld.net/releases/20201014150056/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:269
265| */
266| protected function getRawAttributes(array $attributes = [])
267| {
268| if (! isset($this->definitions[$this->class][$this->name])) {
> 269| throw new InvalidArgumentException("Unable to locate factory with name [{$this->name}] [{$this->class}].");
270| }
271|
272| $definition = call_user_func(
273| $this->definitions[$this->class][$this->name],
Exception trace:
1 Illuminate\Database\Eloquent\FactoryBuilder::getRawAttributes([])
/www/htdocs/w0146a6f/dev/dev4.partner.healyworld.net/releases/20201014150056/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:292
2 Illuminate\Database\Eloquent\FactoryBuilder::Illuminate\Database\Eloquent\{closure}()
/www/htdocs/w0146a6f/dev/dev4.partner.healyworld.net/releases/20201014150056/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php:122
I do the deployment with envoyer.
My factory is defined in database/factories/PayoutFactory.php
<?php
$factory->define(\App\Payout::class, function (Faker\Generator $faker) {
return [
'user_id' => function () {
return factory(App\User::class)->create()->id;
},
'amount' => $faker->randomFloat(2),
'req_amount' => 0,
'tax_amount' => 0,
'withheld' => 0,
'vat_rate' => $faker->randomNumber(2),
'released_amount' => $faker->randomFloat(2),
'released_amount_local_currency' => $faker->randomFloat(2),
'status' => 'released',
'flag' => 0,
'created_at' => $faker->dateTimeBetween('-6 months', 'now'),
];
});
However, it won't work on production. I already cleared the cache, the routes and called composer dump-autoload, but it still failes with the same issue.
Any suggestions?
I also read all answers of Laravel 5.2: Unable to locate factory with name [default] but none of them worked.
Notice this:
Unable to locate factory with name [100]
It looks like factory() is willing to use states instead of quantity. In this case it's looking for a factory state called (string) "100" instead of (int) 100
Cast your amount variable to be an integer
$numberOfPayouts = (int) $this->ask('How many payouts you want to generate?', 10);
Alternatively, try using ->times($amount) method to be more explicit.
I am trying to update a sql database table using the data of an excel file (.csv) in Laravel using the Laravel Excel repository.
My Controller function gives back the content of the excel file, but just in an array of 2 (it should be 604).
Therefore, I think I would have to add 'line ending \t' to my function.But I do not know how.
Here is what I know so far:
The controller
public function uploadExcel()
{
Excel::load(Input::file('import_file'), function ($reader) {
foreach ($reader->toArray() as $value) {
$insert[] = [
'member_title' => $value->member_title,
'member_first_name' => $value->member_first_name,
'member_name_affix' => $value->member_name_affix,
'member_last_name' => $value->member_last_name,
'member_private_address' => $value->member_private_address,
'member_private_zip_code' => $value->member_private_zip_code,
'member_private_location' => $value->member_private_location,
'member_private_phone' => $value->member_private_phone,
'member_private_mobile' => $value->member_private_mobile,
'member_private_fax' => $value->member_private_fax,
'member_private_mail' => $value->member_private_mail,
'member_business_position' => $value->member_business_position,
'member_business_name' => $value->member_business_name,
'member_business_address' => $value->member_business_address,
'member_business_zip_code' => $value->member_business_zip_code,
'member_business_location' => $value->member_business_location,
'member_business_area_code' => $value->member_business_area_code,
'member_business_phone' => $value->member_business_phone,
'member_business_fax' => $value->member_business_fax,
'member_business_mobile' => $value->member_business_mobile,
'member_business_mail' => $value->member_business_mail,
'member_join_date' => $value->member_join_date,
'extra' => $value->extra
];
}
});
if(!empty($insert)) {
die(var_dump($insert)); <-- puts out the array for testing
DB::table('members')->insert($insert);
}
return redirect('index.index');
}
According to the official documentation I would have to add this to my project to recognize the correct line endings:
class UserListImport extends \Maatwebsite\Excel\Files\ExcelFile {
protected $lineEnding = '\t';
}
If my hunch is correct and this snippet from the documentation would solve my problem:
Where do I have to create this file, which contains the code from the documentation? And do I have to change anything else to make that file take affect?
I am really new to Laravel and I would be very thankful for any kind of help!!
UPDATE
Error message
Class App\UserListImport contains 1 abstract method and must therefore
be declared abstract or implement the remaining methods
(Maatwebsite\Excel\Files\ExcelFile::getFile)
app/UserListImport.php
namespace App;
class UserListImport extends \Maatwebsite\Excel\Files\ExcelFile {
protected $lineEnding = '\t';
public function loadExcel() {
Excel::load(Input::file('import_file'), function ($reader) {
foreach ($reader->toArray() as $value) {
$insert[] = [
'member_title' => $value->member_title,
'member_first_name' => $value->member_first_name,
'member_name_affix' => $value->member_name_affix,
'member_last_name' => $value->member_last_name,
'member_private_address' => $value->member_private_address,
'member_private_zip_code' => $value->member_private_zip_code,
'member_private_location' => $value->member_private_location,
'member_private_phone' => $value->member_private_phone,
'member_private_mobile' => $value->member_private_mobile,
'member_private_fax' => $value->member_private_fax,
'member_private_mail' => $value->member_private_mail,
'member_business_position' => $value->member_business_position,
'member_business_name' => $value->member_business_name,
'member_business_address' => $value->member_business_address,
'member_business_zip_code' => $value->member_business_zip_code,
'member_business_location' => $value->member_business_location,
'member_business_area_code' => $value->member_business_area_code,
'member_business_phone' => $value->member_business_phone,
'member_business_fax' => $value->member_business_fax,
'member_business_mobile' => $value->member_business_mobile,
'member_business_mail' => $value->member_business_mail,
'member_join_date' => $value->member_join_date,
'extra' => $value->extra
];
}
});
if(!empty($insert)) {
die(var_dump($insert));
DB::table('members')->insert($insert);
}
return redirect('index.index');
}
}
Controller
use Maatwebsite\Excel\Facades\Excel;
use App\UserListImport;
public function uploadExcel()
{
UserListImport::loadExcel();
}
The docs assumed you created a new custom class extending Excelfile.
class UserListImport extends \Maatwebsite\Excel\Files\ExcelFile
means exacly this.
I usually prefer to add my own application namespaced folders for anything that my application needs.
It this case I would extract anything out from the controller and call my own class to process Input::file('import_file'). That class is the place where to put that attribute to overwrite how the library interacts with the file.
This \t means tabulation(gap between words). For line endings the following combinations of chars are used '\n', '\r\n'. It depends on the operating system. '\n' is for Unix/Linux/Mac OS and '\r\n' is for Windows families.
I have read other answers but nothing solved my issue. When I run php artisan db:seed nothing happens, even no error is thrown.This is my DatabaseSeeder class
<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Model::unguard();
// call our class and run our seeds
$this->call(BearAppSeeder::class);
// $this->call(UserTableSeeder::class);
Model::reguard();
}
}
BearAppSeeder contains following content.
<?php
use Illuminate\Database\Seeder;
class BearAppSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
// clear our database ------------------------------------------
/*DB::table('bears')->delete();
DB::table('fish')->delete();
DB::table('picnics')->delete();
DB::table('trees')->delete();
DB::table('bears_picnics')->delete();*/
// seed our bears table -----------------------
// we'll create three different bears
// bear 1 is named Lawly. She is extremely dangerous. Especially when hungry.
$bearLawly = Bear::insert(['name' => 'Lawly',
'type' => 'Grizzly',
'danger_level' => 8]);
/*/ bear 2 is named Cerms. He has a loud growl but is pretty much harmless.
$bearCerms = Bear::create(array(
'name' => 'Cerms',
'type' => 'Black',
'danger_level' => 4
));
// bear 3 is named Adobot. He is a polar bear. He drinks vodka.
$bearAdobot = Bear::create(array(
'name' => 'Adobot',
'type' => 'Polar',
'danger_level' => 3
));
$this->command->info('The bears are alive!');
// seed our fish table ------------------------
// our fish wont have names... because theyre going to be eaten
// we will use the variables we used to create the bears to get their id
Fish::create(array(
'weight' => 5,
'bear_id' => $bearLawly->id
));
Fish::create(array(
'weight' => 12,
'bear_id' => $bearCerms->id
));
Fish::create(array(
'weight' => 4,
'bear_id' => $bearAdobot->id
));
$this->command->info('They are eating fish!');
// seed our trees table ---------------------
Tree::create(array(
'type' => 'Redwood',
'age' => 500,
'bear_id' => $bearLawly->id
));
Tree::create(array(
'type' => 'Oak',
'age' => 400,
'bear_id' => $bearLawly->id
));
$this->command->info('Climb bears! Be free!');
// seed our picnics table ---------------------
// we will create one picnic and apply all bears to this one picnic
$picnicYellowstone = Picnic::create(array(
'name' => 'Yellowstone',
'taste_level' => 6
));
$picnicGrandCanyon = Picnic::create(array(
'name' => 'Grand Canyon',
'taste_level' => 5
));
// link our bears to picnics ---------------------
// for our purposes we'll just add all bears to both picnics for our many to many relationship
$bearLawly->picnics()->attach($picnicYellowstone->id);
$bearLawly->picnics()->attach($picnicGrandCanyon->id);
$bearCerms->picnics()->attach($picnicYellowstone->id);
$bearCerms->picnics()->attach($picnicGrandCanyon->id);
$bearAdobot->picnics()->attach($picnicYellowstone->id);
$bearAdobot->picnics()->attach($picnicGrandCanyon->id);
$this->command->info('They are terrorizing picnics!');*/
}
}
I have tried running composer dump-autoload but this did not resolve my issue. I am new to Laravel so I do not know too much about it.
I think your model class Bear is not found in BearAppSeeder. So ,
put
use App\Bear;
after
use Illuminate\Database\Seeder;
I hope this may help
Call the seeder class in following way:
$this->call(App\BearAppSeeder::class);
Use App directory name before BearAppSeeder::class
Hello I'm pretty new to PHPUnit and Laravel 4.
I've created an REST API and I'm trying to add a new User using laravel (PHPUnit) unit tests, to my test DB. The problem is, that it completely disregards the Object array that I'm trying to add with the user doc creation.
A typical User Doc would look as follows:
{
_id": ObjectId("53021089b4d15220118b4568"),
"oArr": {
"something": {
"somewhere": "5th Avenue",
"ip": "192.168.0.20"
},
"something2": {
"somewhere": "6th Avenue",
"ip": "192.168.0.21"
}
}
"email": "jessica#example.com",
"name": "Jessica Alba",
"password": "$2y$10$RAVzUGLAG.81IOOUum0k0u5vrcY98H.L42FeSJekEywUCV.ycttn6"
}
Now Laravel has it's own Testing class TestCase which your Unit tests extend.
Typical example would be the following:
class AddUserTest extends TestCase {
/**
* A basic functional test example.
*
* #return void
*/
public function testCreateUsers()
{
$post_data = array(
'email' => 'emma#example.com',
'name' => 'Emma Watson',
'password' => 'password',
'oArr' => array(
'something' => array(
'somewhere' => '7th Avenue',
'ip' : => '192.168.0.31'
),
),
);
}
}
Once the user test has run (successfully), the new Emma Watson user (Mongo Doc) look as follows:
{
_id": ObjectId("53021089b4d15220118b4568"),
"email": "emma#example.com",
"name": "Emma Watson",
"password": "$2y$10$asdAzUGLAG.8asvWQOUum0k0u5vrcY98H.LEDeSJekEywUCV.ycttn6"
}
I have no idea how, and couldn't find anyone else with the same problem.
My assumption: The ORM I'm using (https://github.com/jenssegers/Laravel-MongoDB), doesn't cater for Object arrays in Unit Tests.
I have yet to look into how the ORM is handling unit tests, I'm just hoping someone else has had the same problem, and has a more basic solution.
Well, your test returned modified document. Mongodb is automatically appending new _id to every insertion, that is not explicitly marked as update. Also mongo is hashing you password - it is probably done by you package driver. Since mongodb is using nested document, you test probably didn't reach that nested level, and there is no that document.
Completely forgot about this post.
Laravel's Input class handles for JSON input also. So if you're trying to post embedded documents, you might as well do it in an JSON format. The following worked for me.
class AddUserTest extends TestCase {
/**
* A basic functional test example.
*
* #return void
*/
public function testCreateUsers()
{
$post_data = array(
'email' => 'emma#example.com',
'name' => 'Emma Watson',
'password' => 'password',
'oArr' => array(
'something' => array(
'somewhere' => '7th Avenue',
'ip' : => '192.168.0.31'
),
),
);
$post_data = json_encode($post_data);
// Send through the serialized data to the Controller.
}
}
My general test setup looks something like:
class MySeleniumTest extends PHPUnit_Extensions_SeleniumTestCase{
public static $browsers = array(
array(
'name' => 'Mozilla - Firefox',
'browser' => '*firefox',
'host' => 'localhost',
'port' => 4444,
'timeout' => 30000,
),
array(
'name' => 'Google - Chrome',
'browser' => '*googlechrome',
'host' => 'localhost',
'port' => 4444,
'timeout' => 30000,
)
);
//etc
}
And from here an individual test file looks something like:
class MyTest extends MySeleniumTest{
public function setUp(){
parent::setUp();
$this->setUser(1);
}
public function testPageTitle(){
//Login and open the test page.
$this->login(8);
$this->open('/test/page');
//Check the title.
$this->assertTitle('Test Page');
}
}
From here, when I run MyTest.php with PHPUnit, PHPUnit will automatically run each test case in MyTest.php. Furthermore, it runs each test on each of the specified browsers individually. What I want to be able to do is get information on the driver running a specific test case from within that test case. So something like:
public function testPageTitle(){
//Login and open the test page.
$this->login(8);
$this->open('/test/page');
//Check the title.
$this->assertTitle('Test Page');
$driver = $this->getDriver();
print($driver['browser']); //or something.
}
This however, does not work. And $this->getDrivers() just adds more drivers to the tests, and is only suppose to be used by the setup. Any ideas? Thanks!
Even though $this->drivers is an array there is always only one element in it. You can check that here. So
$this->drivers[0] contains informations about currently running browser and you can use $this->drivers[0]->getBrowser() to output browser name.
Example:
require_once 'MySeleniumTest.php';
class MyTest extends MySeleniumTest{
public function setUp(){
parent::setUp();
$this->setBrowserUrl('http://www.google.com/');
}
public function testPageTitle(){
$this->open('http://google.com');
echo "{$this->drivers[0]->getBrowser()}\n";
}
}
Outputs:
PHPUnit 3.7.18 by Sebastian Bergmann.
.*firefox
.*googlechrome
Time: 7 seconds, Memory: 3.50Mb
OK (2 tests, 0 assertions)