1
votes

I am working on a SilverStripe project. I am writing functional tests for my unit test. Following is the scenario I am trying to test. When a POST request is made, I save the data from the request body into the SilverStripe session. I want to assert/ test that the data are stored in the session.

This is my controller class

    class CustomFormPageController extends PageController
    {
        private static $allowed_actions = [
            'testPostRequest',
        ];

        private static $url_handlers = [
            'testPostRequest' => 'testPostRequest',
        ];

        public function testPostRequest(HTTPRequest $request)
        {
            if (! $request->isPOST()) {
                return "Bad request";
            }

            //here I am saving the data in the session
            $session = $request->getSession();
            $session->set('my_session_key', $request->getBody());

            return "Request successfully processed";
        }
    }

Following is my test class

class CustomFormPageTest extends FunctionalTest
{
    protected static $fixture_file = 'fixtures.yml';

    public function testTestingPost()
    {
        $formPage = $this->objFromFixture(CustomFormPage::class, 'form_page');
         $formPage->publish("Stage", "Live");
        $response = $this->post($formPage->URLSegment . '/testPostRequest', [
            'name' => 'testing'
        ]);

        $request = Injector::inst()->get(HTTPRequest::class);
        $session = $request->getSession();
        $sessionValue = $session->get('my_session_key');

        var_dump($sessionValue);
    }
}

When I run the test, I get the following error.

ArgumentCountError: Too few arguments to function SilverStripe\Control\HTTPRequest::__construct(), 0 passed and at least 2 expected

How can I fix it? How can I test if the data are stored in the session?

I tried this too and it always returns NULL

var_dump($this->session()->get('my_session_key');
1

1 Answers

2
votes

The error you get happens when you ask Injector for the current request before it has created one. This is because FunctionalTest nests the Injector state in which it executes tests.

You can still access the FunctionalTest session using $this->session(), as you've noted.

The main reason your test is failing is because your fixtured page is not published, and FunctionalTest operates in the live stage by default (I'm assuming this, because you didn't post your fixture). You can use the draft stage using protected static $use_draft_site = true; in your test class, or you can publish the page in setUp() or your test before you make the POST request to it.

Your next problem is that $request->getBody() is null in your controller, so it's not setting anything.

This works, for an example:

//here I am saving the data in the session
$session = $request->getSession();
$session->set('my_session_key', $request->postVar('name'));
$response = $this->post($formPage->URLSegment . '/testPostRequest', [
    'name' => 'testing'
]);

$sessionValue = $this->session()->get('my_session_key');

$this->assertSame('testing', $sessionValue);