Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Codecept, unit test: How to mock POST DATA into the request object?

I am trying to create a unit test where I need to simulate form data sent via post. Is there a way to mock POST data?

I've created a class that determines which button was pressed in a way that is independent on its value property. Buttons are placed in a specific button array in the post data (this array only exists if a button was pressed). The pressed button then gets picked up from the request object, and will sometimes be used to determine program flow.

In one of my attempts I created a mock Request object (which I set in the DI) where I override the three methods this test needs: "isPost", "has", and "get".

This way i can control the Request object. What I would like, though, is to control the form values or more specifically I want to change which button is pressed to see how my class behaves in different situations.

Is there a way to do this?



1.8k

If you want to know or simulate which button is pressed, then you're looking at the client-side, i.e. jQuery. You can automate or record anything you want at the client-side with jQuery to provide for your mock tests.

But if you're writing unit tests, you shouldn't be checking for user input or model behaviours. You should be testing internal logic. Check http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/. It's a great read! ;)



4.3k
Accepted
answer
edited Oct '14

Thanks, I see now that what I was about to do was not unit testing but rather functional or integration testing.

Though I have no use for it right now I would still like to know if it's possible from inside Phalcon to manipulate the POST data that gets injected into the Request object.

I solved my issues like this (any critique is apperciated):

0) The unit I want to test is an extension of Phalcon\Mvc\Component

# MyApp/Library/SubmitIdentifier/SubmitIdentifier.php
<?php
namespace MyApp\Library\SubmitIdentifier;

use Phalcon\Mvc\User\Component;

class SubmitIdentifier extends Component
{
    /**
     * @var null|string
     */
    public $action = null;

    /**
     * part of a dispatch logic built around submit buttons
     * Submit button input fields must be named <submit_array_name>[xxx] (eg. btn[xxx]) where xxx identifies the intended action (decided by the developer)
     * Because the "value" of a submit button is used for non-data purposes the xxx-key replaces this functionality
     * it is through this possible to treat the xxx-key equivalently to the "value" of other form fields
     *  
     * @param string  $submit_array_name root name of the button array: default is btn
     * 
     */
    public function initialize($submit_array_name='btn')
    {
        if ($this->request->isPost() && $this->request->has($submit_array_name)) {
            $btn = $this->request->get($submit_array_name);
            if(is_array($btn)) {
                $this->action = key($btn);
            }
        }
    }

    /**
     * Returns the index for the pressed button in the btn[] array
     * @return mixed|null
     */
    public function getAction($submit_array_name='btn')
    {
        if(is_null($this->action)) {
            $this->initialize($submit_array_name);
        }
        return $this->action;
    }
}

1) I created a special request class extending Phalcon\Http\Request

#tests/unit/SubmitIdentifierHelper.php
<?php
class SubmitIdentifierHelper extends \Phalcon\Http\Request 
{
    public $post_data;

    public function isPost() {
        $res = parent::isPost();
        return true;
    }
    public function has($name) {
        $res = parent::has($name);
        return true;
    }
    public function get($name=null,$filters=null,$defaultValue=null) {
        $res = parent::get($name,$filters,$defaultValue);
        return $this->post_data[$name];
    }
}

2) I set up my test like this:

#tests/unit/SubmitIdentifierTest.php
<?php

class SubmitIdentifierTest extends \Codeception\TestCase\Test
{
    ...

    public function testSubmitIdentifier()
    {
        $SubmitIdentifier = new \MyApp\Library\SubmitIdentifier\SubmitIdentifier();

        include __DIR__."/SubmitIdentifierHelper.php";
        $SubmitIdentifier->request = new SubmitIdentifierHelper();
        $SubmitIdentifier->request->post_data = array('btn' => array('cmp_submit'=>null));

        $this->assertEquals('cmp_submit',$SubmitIdentifier->getAction());
    }
}