How to use data providers to create a test that runs before each test in a class?

Viewed 35

I'm trying to test a class that handles a user's collection of favorite items, which can be of different types, eg. movies and songs.

So I have this base test class (I'm using Codeception, which uses Phpunit):

class BaseCollectionTest extends \Codeception\Test\Unit {  

   public function setUp() : void {

      parent::setUp();

      $this->userId = $this->tester->createUser();     
      $this->tester->login( $this->userId ); 

   }
 
   public function dataProvider() {
      return [
         [ new CollectionService( "movies", $this->userId ) ],
         [ new CollectionService( "songs", $this->userId ) ]
      ]; 
   }

}

Now I want to test whether a user can rename an existing collection, so I would like to create a collection first before the renaming tests are executed. IDEALLY, I could do this:

class RenameCollectionTest extends BaseCollectionTest {

   protected $collection;
   protected $Service;

   /**
    * @dataProvider dataProvider
    */

   public function setUp( $Service ) : void {

      parent::setUp();

      $this->Service = $Service; 
      $this->collection = $this->Service->create_collection();
   
   }

   public function testRenamesCollection() {
      $renamedCollection = $this->Service->rename_collection( $this->collection["id"], "New Title" ); 
      $this->assertEquals( $renamedCollection["title"], "New Title" ); 
   }

}

However, I've read that data providers can't be used with setUp. So I've tried a bunch of workarounds, most notably this:

class RenameCollectionTest extends BaseCollectionTest {

   /**
    * @dataProvider dataProvider
    */
   public function testCreatesCollection( $Service ) {
      $this->Service = $Service; 
      return $this->Service->create_collection();
   }

   /**
    * @depends testCreatesCollection
    */
   public function testRenamesCollection( array $collection ) {
      $renamedCollection = $this->Service->rename_collection( $collection["id"], "New Title" ); 
      $this->assertEquals( $renamedCollection["title"], "New Title" ); 
   }

}

From what I've read, testRenamesCollection should receive the result of testCreatesCollection as its argument because of the @depends annotation, but I get a type error complaining that $collection received by testRenamesCollection is null and not an array (although I have verified that the return value of testCreatesCollection is in fact an array with the newly created collection data).

What other options do I have other than having to create a collection in each one of the renaming tests?

1 Answers

It seems you don't need you first test (which doesn't assert anything ?)

Indeed you can't put any logic in dataproviders, the easiest way for me should be:

public function dataProvider() 
{
  return [
     [ "movies", $this->userId ],
     [ "songs", $this->userId ]
  ]; 
}

/**
 * @dataProvider dataProvider
 */
public function testCreatesAndRenamesCollection( $collectionName, $userId ) 
{
    $this->Service = new CollectionService( $collectionName, $userId ); 
    $collection = $this->Service->create_collection();
    $renamedCollection = $this->Service->rename_collection( $collection["id"], "New Title" ); 
    
    $this->assertEquals( $renamedCollection["title"], "New Title" ); 
}

(I would rather use simple properties in dataproviders to avoid duplicate code and have better maintanibility)

Related