5

I'm receiving the below error when running my unit tests. Seems that it doesn't like passing in the Input::get to the constructor, however when running the script within the browser the action works fine so I know it's not the controller code. If I take out any of the 'task_update' code the test passes with just the find even with the Input - so not sure why it accepts the Input for one method.

ErrorException: Argument 1 passed to Illuminate\Database\Eloquent\Model::__construct() must be of the type array, null given, called

My Controller is:

public function store()
{
    $task_update = new TaskUpdate(Input::get('tasks_updates'));

    $task = $this->task->find(Input::get('tasks_updates')['task_id']);

    $output = $task->taskUpdate()->save($task_update);

    if (!!$output->id) {
        return Redirect::route('tasks.show', $output->task_id)
                        ->with('flash_task_update', 'Task has been updated');
    }
}

And the test is - I'm setting the input for task_updates array but just isn't being picked up:

    Input::replace(['tasks_updates' => array('description' => 'Hello')]);

    $mockClass = $this->mock;
    $mockClass->task_id = 1;

    $this->mock->shouldReceive('save')
               ->once()
               ->andReturn($mockClass);

    $response = $this->call('POST', 'tasksUpdates');

    $this->assertRedirectedToRoute('tasks.show', 1);
    $this->assertSessionHas('flash_task_update');

2 Answers 2

4

I believe the "call" function is blowing away the work done by Input::replace.

the call function can actually take a $parameters parameter which should fix your problem.

if you look in \Illuminate\Foundation\Testing\TestCase@call, you'll see the function:

/**
 * Call the given URI and return the Response.
 *
 * @param  string  $method
 * @param  string  $uri
 * @param  array   $parameters
 * @param  array   $files
 * @param  array   $server
 * @param  string  $content
 * @param  bool    $changeHistory
 * @return \Illuminate\Http\Response
 */
public function call()
{
    call_user_func_array(array($this->client, 'request'), func_get_args());

    return $this->client->getResponse();
}

If you do:

$response = $this->call('POST', 'tasksUpdates', array('your data here'));

I think it should work.

Sign up to request clarification or add additional context in comments.

Comments

1

I do prefer to do both Input::replace($input) and $this->call('POST', 'path', $input).

Example AuthControllerTest.php:

public function testStoreSuccess()
{
    $input = array(
        'email' => '[email protected]', 
        'password' => 'password',
        'remember' => true
        );

    // Input::replace($input) can be used for testing any method which      
    // directly gets the parameters from Input class
    Input::replace($input);



    // Here the Auth::attempt gets the parameters from Input class
    Auth::shouldReceive('attempt')
    ->with(     
            array(
                    'email' => Input::get('email'),
                    'password' => Input::get('password')
            ), 
            Input::get('remember'))
    ->once()
    ->andReturn(true);

    // guarantee we have passed $input data via call this route
    $response = $this->call('POST', 'api/v1/login', $input);
    $content = $response->getContent();
    $data = json_decode($response->getContent());

    //... assertions

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.