Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem running test on models using phpUnit #12

Closed
edsuna opened this issue Apr 2, 2014 · 13 comments
Closed

Problem running test on models using phpUnit #12

edsuna opened this issue Apr 2, 2014 · 13 comments

Comments

@edsuna
Copy link

edsuna commented Apr 2, 2014

I am using the uniquewith validation without a problem in my application. I am trying to write some tests now. However, when I try to run a test in PHPUnit it gives me the following error:
BadMethodCallException: Method [validateUniqueWith] does not exist

What do I need to do in order for this to work in my unit tests?

Thanks

@livkiss
Copy link
Owner

livkiss commented Apr 2, 2014

Can you provide the test class including the related test method?

@edsuna
Copy link
Author

edsuna commented Apr 2, 2014

class PhoneVarModelTest extends TestCase {
/**
* @ExpectedException LaravelBook\Ardent\InvalidModelException
*/
public function testNameIsRequired()
{
$phoneVar = new PhoneVar();
$phoneVar->description = "Desc";
$phoneVar->variable_type = "Text";
$phoneVar->default_value = "Def";
$this->assertFalse($phoneVar->save());
}

public function testInsert()
{
$phoneVar = new PhoneVar();
$phoneVar->name = "Var";
$phoneVar->description = "Desc";
$phoneVar->variable_type = "Text";
$phoneVar->default_value = "Def";
$phoneVar->phone_model_id = 1;
$this->assertTrue($phoneVar->save());
}
}

Function testInsert fails with the error I reported.

This is the model class that I am testing
class PhoneVar extends Ardent {
protected $guarded = array();

/**
* Validation Rules
* @var array
*/
public static $rules = array(
'name' =>
'required|unique_with:phone_variables,phone_model_id|alpha_num|between:4,16',
'description' => 'required',
'default_value' => 'required'
);

/**
* hydrates on new entries' validation
* @var boolean
/
public $autoHydrateEntityFromInput = false;
/
*
* hydrates whenever validation is called
* @var boolean
*/
public $forceEntityHydrationFromInput = false;

/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'phone_variables';

/**
* Have the model throw an error if validation fails
* @var boolean
*/
public $throwOnValidation = true;

/**
* Create the belongsTo relationship with PhoneModel
* @return object
*/
public function phoneModel()
{
return $this->belongsTo('PhoneModel');
}
}
On 4/2/2014 1:22 PM, Felix Kiss wrote:

Can you provide the test class including the related test method?


Reply to this email directly or view it on GitHub
#12 (comment).

David Suna
david@davidsconsultants.com

@livkiss
Copy link
Owner

livkiss commented Apr 2, 2014

I haven't completely figured this out myself, but try doing as suggested in this issue:

class PhoneVarModelTest extends PHPUnit_Framework_TestCase {
    // ...
}

Let me know if it helped

@edsuna
Copy link
Author

edsuna commented Apr 2, 2014

Unfortunately this didn't help.
I get the same error

On 4/2/2014 2:26 PM, Felix Kiss wrote:

I haven't completely figured this out myself, but try doing as
suggested in this issue
JeffreyWay/Laravel-Model-Validation#4 (comment):

class PhoneVarModelTest extends PHPUnit_Framework_TestCase {
// ...
}

Let me know if it helped


Reply to this email directly or view it on GitHub
#12 (comment).

David Suna
david@davidsconsultants.com

@livkiss
Copy link
Owner

livkiss commented Apr 2, 2014

I tried to create a similar scenario to yours (ardent + uniquewith-validator) in a fresh copy of laravel.
felixkiss/uniquewith-validator-issue-debug/tree/issue-12

It works. What are the differences between my proof of concept and your application?
Please provide more information (Laravel version, composer.json, etc.) or look at the repository mentioned above.

@edsuna
Copy link
Author

edsuna commented Apr 2, 2014

Laravel version is v4.1.24

Here is my composer.json
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
"laravel/framework": "4.1.",
"cartalyst/sentry": "2.1.
",
"illuminate/database": "4.1.",
"ircmaxell/password-compat": "
",
"rydurham/sentinel": "1.",
"doctrine/dbal": "~2.3",
"laravelbook/ardent": "dev-master",
"felixkiss/uniquewith-validator": "1.0.
"
},
"require-dev": {
"barryvdh/laravel-debugbar": "1.",
"phpunit/phpunit": "3.7.
",
"way/generators": "1.1"
},
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
},
"scripts": {
"post-install-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"post-update-cmd": [
"php artisan clear-compiled",
"php artisan optimize",
"php artisan debugbar:publish"
],
"post-create-project-cmd": [
"php artisan key:generate"
]
},
"config": {
"preferred-install": "dist"
},
"minimum-stability": "stable"
}

David Suna
david@davidsconsultants.com

@edsuna
Copy link
Author

edsuna commented Apr 2, 2014

I think I found the problem. I had implemented some of my own custom validations and that caused the validation methods defined in your package to not get loaded. I am not exactly sure why but that seems to be what happened. Rather than try to figure out how to resolve the conflict I just implemented my own unique_with type of validation.

@edsuna edsuna closed this as completed Apr 2, 2014
@spawn-guy
Copy link

I'd like to reopen this Issue. As i seem to get the same error.
this IS related to unique_with and Ardent, but.. the problem lies in the
Ardent()->updateUniques(); (and not in ->save())
which prepares the ruleset and inserts the id in the "unique" rule
protected function buildUniqueExclusionRules()
it, basically, overrides the "unique_with" to just "unique" but with proper id in the rule

I'm now trying to fix it somehow, or i'm just mistaken and diggin' in the wrong place :|

@livkiss
Copy link
Owner

livkiss commented May 19, 2014

Do you use a BaseModel class for shared functionality?

It should be something like this

class BaseModel extends Ardent
{
/**
     * When given an ID and a Laravel validation rules array, this function
     * appends the ID to the 'unique' rules given. The resulting array can
     * then be fed to a Ardent save so that unchanged values
     * don't flag a validation issue. Rules can be in either strings
     * with pipes or arrays, but the returned rules are in arrays.
     *
     * @param int   $id
     * @param array $rules
     *
     * @return array Rules with exclusions applied
     */
    protected function buildUniqueExclusionRules(array $rules = array()) {

        if (!count($rules))
          $rules = static::$rules;

        foreach ($rules as $field => &$ruleset) {
            // If $ruleset is a pipe-separated string, switch it to array
            $ruleset = (is_string($ruleset))? explode('|', $ruleset) : $ruleset;

            foreach ($ruleset as &$rule) {
              if (strpos($rule, 'unique') === 0) {
                $params = explode(',', $rule);

                $uniqueRules = array();

                // Append table name if needed
                $table = explode(':', $params[0]);
                $ruleName = $table[0]; // Updated
                if (count($table) == 1)
                  $uniqueRules[1] = $this->table;
                else
                  $uniqueRules[1] = $table[1];

                // Append field name if needed
                if (count($params) == 1)
                  $uniqueRules[2] = $field;
                else
                  $uniqueRules[2] = $params[1];

                if (isset($this->primaryKey)) {
                  $uniqueRules[3] = $this->{$this->primaryKey};
                  $uniqueRules[4] = $this->primaryKey;
                }
                else {
                  $uniqueRules[3] = $this->id;
                }

                $rule = $ruleName . ':' . implode(',', $uniqueRules);  // Updated
              } // end if strpos unique

            } // end foreach ruleset
        }

        return $rules;
    }
}

@livkiss livkiss reopened this May 19, 2014
@spawn-guy
Copy link

okay, apparently i was misusing part of the thing.

I thought it would act as INSERT on DUPLICATE KEY UPDATE. i.e. ovewritten on save...
$record = new Model();
$record->set-multiple-columns;
$record->updateUniques();

but It seems that at first you override a findOrNew or findOrCreate with ability to find by multiple UNIQUE columns+values. and only Then you try to updateUniques() (which replaces the "unique_with" with "unique" and a proper primaryKey and it's value), and THEN it works as expected.

@spawn-guy
Copy link

@felixkiss yes i was trying to override this method, but it seems that it has a different purpose :|
so i ended up overriding the findOrNew method.

if you wish, we can continue with this issue (Ardent and unique_with) as it seems to not support multi-column primary keys at all.

i.e. in the code shown, multy-column primary key will fail,.. hard :)

@livkiss
Copy link
Owner

livkiss commented May 19, 2014

From my understanding, Ardent tries to append the id to the unique rule in order to ignore it.

unique_with supports this feature too (passing an ID at the end to ignore it), but the problem is, it takes all rules starting with unique (thus, also affecting unique_with rules), but always overrides the rule name with unique. So a unique_with rule will be replace by a unique rule.

Anyways, make sure you test your code with some values that would violate the multiple UNIQUE declaration of your SQL schema to make sure it does what you expect it to.

Please close the issue whenever you feel it is resolved for you.

Cheers

@livkiss
Copy link
Owner

livkiss commented Aug 7, 2014

Seems like a resolved issue to me. Reopen if more help is needed.

@livkiss livkiss closed this as completed Aug 7, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants