How can I mock a method that should accept an array?

1.4k views Asked by At

I am new to testing with PHPUnit, and what I am trying to do is test a method called returnOnLogin() that accepts a parameter Enlight_Event_EventArgs $args and returns true.

Here's the method I want to test:

public function returnOnLogin(\Enlight_Event_EventArgs $args)
{
    $controller = $args->get('subject');
    $view = $controller->View();

    $controller->redirect([
        'controller' => 'verification'
    ]);

    // $view->addTemplateDir(
    // __DIR__ . '/Views'
    // );

    return true;
}

Here's my test:

class MyFirstTestPluginTest extends TestCase
{
    public function testReturnOnLogin()
    {
        $my_plugin = new MyFirstTestPlugin(true);
        $expected = true;

       //I tried following but it did not work
       $this->assertEquals($expected, $my_plugin->returnOnLogin(//here is the problem it requires this array that I dont know));
   }

}

1

There are 1 answers

1
localheinz On BEST ANSWER

Assuming that your controller class is Controller, and assuming that we don't care that view() is invoked in $controller, this should cover what you are looking for:

class MyFirstTestPluginTest extends TestCase
{
    public function testReturnOnLogin()
    {
        /**
         * create a test double for the controller (adjust to your controller class)
         */
        $controller = $this->createMock(Controller::class);

        /**
         * expect that a method redirect() is called with specific arguments
         */
        $controller
            ->expects($this->once())
            ->method('redirect')
            ->with($this->identicalTo([
                'controller' => 'verification'
            ]));

        /**
         * create a test double for the arguments passed to returnLogin()
         */
        $args = $this->createMock(\Enlight_Event_EventArgs::class);

        /** 
         * expect that a method subject() is invoked and return the controller from it
         */
        $args
            ->expects($this->once())
            ->method('subject')
            ->willReturn($controller);

        $plugin = new MyFirstTestPlugin(true);

        $this->assertTrue($plugin->returnOnLogin($args));
    }
}

What does this test do?

Arrange

This test first arranges test doubles for use with the system under test (your plugin).

The first test double is your controller, we set it up in such a way that we expect that a method redirect() is invoked once with an argument that is identical to the specified array.

The second test double is the argument, we set it up in such a way that we expect that a method 'subject()` is invoked one, and will return the controller.

Then, we set up the system under test, simply by creating an instance of MyFirstTestPlugin, passing true to the constructor.

Unfortunately, you haven't shared the constructor with us, we have no idea what the argument true stands for. If it affects the behaviour of returnLogin(), then we clearly need to add more tests to assert the behaviour when the argument takes different values.

Act

Then this test invokes the method returnLogin() on the system under test, and passes in one of the test doubles.

Assert

Eventually, this test asserts that the method returnLogin() returns true.

Note Take a look at