Welcome Guest, Not a member yet? Register   Sign In
Problem with testing validation
#1

(This post was last modified: 06-07-2023, 08:04 AM by massimiliano1.mancini.)

I have a bunch of HTTP Feature tests. Some of that simply test that calling a post with correct fields a row in DB is added. For example:

PHP Code:
public function testInsertNewSectionCreateRowInDb()
{
    $dataPost = ['csrf_test_name' => csrf_hash(), 'description' => 'test section'];
    $dataDB = ['description' => 'test section'];
        
    $result 
$this->withRoutes($this->routes)->post('section/create'$dataPost);
        
    $this
->seeInDatabase('section'$dataDB);


others test that invalid input do not add a new row in DB. For example (description is required):

PHP Code:
public function testInsertNewEmptySectionDoNotCreateRowInDb()
{
    $dataPost = ['csrf_test_name' => csrf_hash(), 'description' => ''];
    $dataDB = ['description' => ''];
        
    $result 
$this->withRoutes($this->routes)->post('section/create'$dataPost);
        
    $this
->dontSeeInDatabase('section'$dataDB);


Now, if I test in this order, i.e. tests with no validation errors before and tests with validation errors after, everithing is fine but if I run in the opposite order than all tests fail.
I tried to investigate the cause and I think it depends on a shared validation service whom error array maintain last values. In particular in BaseService.php I found that when recall a static istance it comes back with array error not cleared

PHP Code:
protected static function getSharedInstance(string $key, ...$params)
{
 
$key strtolower($key);

 
// Returns mock if exists
 
if (isset(static::$mocks[$key])) {
 return static::
$mocks[$key];
 }

 if (! isset(static::
$instances[$key])) {
 
// Make sure $getShared is false
 
$params[] = false;

 static::
$instances[$key] = AppServices::$key(...$params);
 }

 return static::
$instances[$key];


Running tests in a predefined order is not a good practice and so I'm asking for some advice and help on how to solve.

EDIT:
I'm not sure if this could be the right solution (or simply it skips all validations), but it works fine if this line

PHP Code:
Services::injectMock('validation'Services::validation(nullfalse)); 
is added before tests that do not need validation and come after tests that failed in validation.


Thank you
Massimiliano
Reply
#2

Try this:
Code:
--- a/system/Test/FeatureTestTrait.php
+++ b/system/Test/FeatureTestTrait.php
@@ -175,6 +175,9 @@ trait FeatureTestTrait
        // Make sure filters are reset between tests
        Services::injectMock('filters', Services::filters(null, false));

+        // Make sure validation is reset between tests
+        Services::injectMock('validation', Services::validation(null, false));
+
        $response = $this->app
            ->setContext('web')
            ->setRequest($request)
Reply
#3

I sent a PR to fix: https://github.com/codeigniter4/CodeIgniter4/pull/7548
Reply
#4

(This post was last modified: 06-07-2023, 11:29 PM by massimiliano1.mancini.)

I tried and it works perfectly.

Thank you

(06-07-2023, 02:38 PM)kenjis Wrote: Try this:
Code:
--- a/system/Test/FeatureTestTrait.php
+++ b/system/Test/FeatureTestTrait.php
@@ -175,6 +175,9 @@ trait FeatureTestTrait
        // Make sure filters are reset between tests
        Services::injectMock('filters', Services::filters(null, false));

+        // Make sure validation is reset between tests
+        Services::injectMock('validation', Services::validation(null, false));
+
        $response = $this->app
            ->setContext('web')
            ->setRequest($request)
Reply




Theme © iAndrew 2016 - Forum software by © MyBB