I have a generate() method on my class which is just a shorthand way to create an instance of the class. It accepts a request which is type hinted on the method. I am trying to unit test this and the only way I know how is to make an answer and pass that through. That doesn’t work tho because it is not a request. Is there a work around for this? Here is the method:
public static function generate(Question $question, Request $request): self
{
return self::create([
'user_id' => Auth::user()->getKey(),
'question_id' => $question->getKey(),
'answer_body' => $request->answer_body,
]);
}
Here is the test
/** #test */
public function it_can_generate_a_new_instance()
{
$user = factory(User::class)->create();
$this->actingAs($user);
$question = factory(Question::class)->create();
$answer = factory(Answer::class)->make();
Answer::generate($question, $answer);
$this->assertEquals($user->getKey(), Answer::first()->user_id);
$this->assertEquals($question->getKey(), Answer::first()->question_id);
$this->assertEquals($answer->answer_body, Answer::first()->answer_body);
}
The test passes until I type hint Request in the method.
You can make a new request object with the given property. It's probably a bit flimsy but it should work:
public function it_can_generate_a_new_instance()
{
$user = factory(User::class)->create();
$this->actingAs($user);
$question = factory(Question::class)->create();
$answer = factory(Answer::class)->make();
$request = new Request([ 'answer_body' => $answer->answer_body ]);
Answer::generate($question, $request);
$this->assertEquals($user->getKey(), Answer::first()->user_id);
$this->assertEquals($question->getKey(), Answer::first()->question_id);
$this->assertEquals($answer->answer_body, Answer::first()->answer_body);
}
a request should only be present on a controller, and not in the Model Answer (Or you will encounter errors like that ^^)
If your process require a request, then you should test an http request instead :
/** #test */
public function it_can_generate_a_new_instance()
{
$user = factory(User::class)->create();
$this->actingAs($user);
$question = factory(Question::class)->create();
$answer = factory(Answer::class)->make();
$this->post(route('answer.store'), $answer->toArray());
// Then your answer will be generated in your controller
$this->assertEquals($user->getKey(), Answer::first()->user_id);
$this->assertEquals($question->getKey(), Answer::first()->question_id);
$this->assertEquals($answer->answer_body, Answer::first()->answer_body);
}
Related
I'm new learner of Symfony 4 and I'm looking for help. I've an Entity named "Player" and I want to generate a random confirmation number.
For now, I'm using a variable $confirmNbr and I save the $confirm in my database with $participant->setConfirmationNumber($confirmNbr);.
What I want it's create a function generateRandomNumber() in my Entity Player.php like this :
public function generateConfirmationNumber() : self
{
$this->confirmationNumber = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',6)),0,5);
return $this;
}
This is my Controller file
/**
* #Route("/", name="homepage")
*/
public function new(Player $player, EntityManagerInterface $em, Request $request)
{
$participant = $this->playerrepo->findAll();
$form = $this->createForm(PlayerFormType::class);
$randomNbr = $player->generateConfirmationNumber();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$participant = new Player;
$participant->setName($data['name']);
$participant->setFirstname($data['firstname']);
$participant->setEmail($data['email']);
$participant->setConfirmationNumber($confirmNbr);
$participant->setRegisterAt(new \DateTime);
$em->persist($player);
$em->flush();
$this->addFlash('success', 'Player added!');
return $this->redirectToRoute('homepage');
}
return $this->render('app/subscribe.html.twig', [
'playerForm' => $form->createView(),
'player'=>$player,
]);
}
And this is my error message :
Unable to guess how to get a Doctrine instance from the request
information for parameter "player".
Can you help me please ?
Your method is expecting an instance of the Player object - where should it come from? Doctrine is trying to guess it and get it from the URL, but it cannot. Your method is for creating new players - why do you need an instance of a player? Just remove that parameter from the method signature, i.e. change it to:
public function new(EntityManagerInterface $em, Request $request)
I've found the solution. I've modified my set function and deleted my function that I've added. Everything works!
I have to call a function from one controller an other controller.
public function getquickviews(Request $request){
$report = new ReportController();
$report ->Applications($request->except('cl_e_start_date'));//it's not working its giving me error that it expect and instance of Request and passed array()
}
public function Applications(Request $request)
{
/*APP USAGE*/
}
and I have to pass instance of Request to Application function. But the issue I don't wanted to pass all the parameter from getquickviews Request like if I am getting email,phone,name on the getquickviews function but I only have to pass phone,email to Application function.
You need to create a new instance of Request.
public function getquickviews(Request $request){
$report = new ReportController();
$content = new Request();
$content->something = $request->something;
$content->somethingElse = $request->somethingElse;
$report ->Applications($content);
}
and then you have to recieve it in:
public function Applications(Request $request)
{
/*APP USAGE*/
}
and that's it.
Regards.
Change this line
$report ->Applications($request->except('cl_e_start_date'));
To
$report ->Applications($request);
try as following (not sure it's gonna work) :
public function getquickviews(Request $request){
$returnedRequest = $request; // do whatever with your request here
return redirect()->route('SecondController.Applications', compact('returnedRequest'));
}
public function Applications(Request $request){
/*APP USAGE*/
}
To be able to create a custom request and thus use it to reference a post method in a controller, you need to first initiate an instance of Request as #martin Carrasco has described above:
the code below is a continuation of martin Carrasco
public function getquickviews(Request $request){
$report = new ReportController();
$content = new Request
([
'firstParam' => $request->param1,
'secondParam' => $request ->param2,
]);
$report ->Applications($content);
}
Try that n hope it works.
I think this will work :
$report ->Applications($request->toArray());
Two ways to get requests into next method or any next level call.
First you can inject Request class depenednacy into that method for an example:
public function store(Request $request)
{
// Form Submits here
}
If you want to pass $request into other method for example to display data after insert you can do this way:
public function showStore(Request $request)
{
dd($request->get());
}
Then you can call this method from store method
$this->showStore($request);
or second is you can use request as metho into showStore or any n level call. Like this:
public function showStore()
{
dd(request()->all());
}
$this->showStore(); // You do not require any injection.
Good Luck!!!
You can keep the particular key and value you want and delete the rest from the $request before passing it to the function. First convert the $request to array by
$request->toArray()
and then delete the unwanted keys by doing
unset($request['key-here']);
and then pass it to the function
$report ->Applications($request);
Repeated Calls – Lets say you need your Application to talk to an API and you're using guzzle or a wrapper or whatever. I find myself having to call the connection in every controller function e.g:
class ExampleController extends Controller
{
public function one()
{
$client = new Client();
$response = $client->get('http://',
[ 'query' => [ 'secret' => env('SECRET')]]);
$json = json_decode($response->getBody());
$data = $json->object;
// do stuff
}
public function two()
{
$client = new Client();
$response = $client->get('http://',
[ 'query' => [ 'secret' => env('SECRET')]]);
$json = json_decode($response->getBody());
$data = $json->object;
// do stuff
}
}
How do I better handle this? Do I use a service Provider? if so, how would I best implement these calls? Should I create another controller and call all my API connections in each function and then include that controller and call upon each function as required? Should I place it in a __construct?
lets try the Dependency inversion principle
Ok this might sound a bit hard at first and my code might have some typos or minor mistakes but try this
You need to create the interface
namespace app\puttherightnamespace; // this deppends on you
interface ExempleRepositoryInterface
{
public function getquery(); // if you passinga variable -> public function getquery('variable1');
}
Now you have to create the repo
class ExempleRepository implements ExempleRepositoryInterface {
public function getquery() {
$client = new Client();
$response = $client->get('http://',
[ 'query' => [ 'secret' => env('SECRET')]]);
$json = json_decode($response->getBody());
return $json->object;
}
Now last step is to bind the interface to the repo in a service provider register method
public function register()
{
$this->app->bind('namespacehere\ExempleRepositoryInterface', 'namespacehere\ExempleRepository');
}
Now everytime you need the result in a controller all you have to do is to ineject
class ExempleController extends Controller {
private $exemple;
public function __construct(ExempleRepositoryInterface $home) {
$this->exemple = $exemple;
}
public function test() {
$data = $this->exemple->getquery(); / you can pass a variable here if you want like this $this->exemple->getquery('variable');
// do stuff
}
this is not the simplest way but this is the best way i guess
Alright so I'm pretty new to both unit testing, mockery and laravel. I'm trying to unit test my resource controller, but I'm stuck at the update function. Not sure if I'm doing something wrong or just thinking wrong.
Here's my controller:
class BooksController extends \BaseController {
// Change template.
protected $books;
public function __construct(Book $books)
{
$this->books = $books;
}
/**
* Store a newly created book in storage.
*
* #return Response
*/
public function store()
{
$data = Input::except(array('_token'));
$validator = Validator::make($data, Book::$rules);
if($validator->fails())
{
return Redirect::route('books.create')
->withErrors($validator->errors())
->withInput();
}
$this->books->create($data);
return Redirect::route('books.index');
}
/**
* Update the specified book in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
$book = $this->books->findOrFail($id);
$data = Input::except(array('_token', '_method'));
$validator = Validator::make($data, Book::$rules);
if($validator->fails())
{
// Change template.
return Redirect::route('books.edit', $id)->withErrors($validator->errors())->withInput();
}
$book->update($data);
return Redirect::route('books.show', $id);
}
}
And here are my tests:
public function testStore()
{
// Add title to Input to pass validation.
Input::replace(array('title' => 'asd', 'content' => ''));
// Use the mock object to avoid database hitting.
$this->mock
->shouldReceive('create')
->once()
->andReturn('truthy');
// Pass along input to the store function.
$this->action('POST', 'books.store', null, Input::all());
$this->assertRedirectedTo('books');
}
public function testUpdate()
{
Input::replace(array('title' => 'Test', 'content' => 'new content'));
$this->mock->shouldReceive('findOrFail')->once()->andReturn(new Book());
$this->mock->shouldReceive('update')->once()->andReturn('truthy');
$this->action('PUT', 'books.update', 1, Input::all());
$this->assertRedirectedTo('books/1');
}
The issue is, when I do it like this, I get Mockery\Exception\InvalidCountException: Method update() from Mockery_0_Book should be called exactly 1 times but called 0 times. because of the $book->update($data) in my controller. If I were to change it to $this->books->update($data), it would be mocked properly and the database wouldn't be touched, but it would update all my records when using the function from frontend.
I guess I simply just want to know how to mock the $book-object properly.
Am I clear enough? Let me know otherwise. Thanks!
Try mocking out the findOrFail method not to return a new Book, but to return a mock object instead that has an update method on it.
$mockBook = Mockery::mock('Book[update]');
$mockBook->shouldReceive('update')->once();
$this->mock->shouldReceive('findOrFail')->once()->andReturn($mockBook);
If your database is a managed dependency and you use mock in your test it causes brittle tests.
Don't mock manage dependencies.
Manage dependencies: dependencies that you have full control over.
I am very new to symfony. In other languages like java and others I can use request.getParameter('parmeter name') to get the value.
Is there anything similar that we can do with symfony2.
I have seen some examples but none is working for me. Suppose I have a form field with the name username. In the form action I tried to use something like this:
$request = $this->getRequest();
$username= $request->request->get('username');
I have also tried
$username = $request->getParameter('username');
and
$username=$request->request->getParameter('username');
But none of the options is working.However following worked fine:
foreach($request->request->all() as $req){
print_r($req['username']);
}
Where am I doing wrong in using getParameter() method. Any help will be appreciated.
The naming is not all that intuitive:
use Symfony\Component\HttpFoundation\Request;
public function updateAction(Request $request)
{
// $_GET parameters
$request->query->get('name');
// $_POST parameters
$request->request->get('name');
Update Nov 2021: $request->get('name') has been deprecated in 5.4 and will be private as of 6.0. It's usage has been discouraged for quite some time.
I do it even simpler:
use Symfony\Component\HttpFoundation\Request;
public function updateAction(Request $request)
{
$foo = $request->get('foo');
$bar = $request->get('bar');
}
Another option is to introduce your parameters into your action function definition:
use Symfony\Component\HttpFoundation\Request;
public function updateAction(Request $request, $foo, $bar)
{
echo $foo;
echo $bar;
}
which, then assumes that you defined {foo} and {bar} as part of your URL pattern in your routing.yml file:
acme_myurl:
pattern: /acme/news/{foo}/{bar}
defaults: { _controller: AcmeBundle:Default:getnews }
You can Use The following code to get your form field values
use Symfony\Component\HttpFoundation\Request;
public function updateAction(Request $request)
{
// retrieve GET and POST variables respectively
$request->query->get('foo');
$request->request->get('bar', 'default value if bar does not exist');
}
Or You can also get all the form values as array by using
$request->request->all()
try
$request->request->get('acme_demobundle_usertype')['username']
inspect attribute name of your formular field
Inside a controller:
$request = $this->getRequest();
$username = $request->get('username');
As now $this->getRequest() method is deprecated you need to inject Request object into your controller action like this:
public function someAction(Request $request)
after that you can use one of the following.
If you want to fetch POST data from request use following:
$request->request->get('var_name');
but if you want to fetch GET data from request use this:
$request->query->get('var_name');
Your options:
Simple:
$request->request->get('param') ($_POST['param']) or
$request->query->get('param') ($_GET['param'])
Good Symfony forms with all validation, value transormation and form rendering with errors and many other features:
http://symfony.com/doc/current/book/forms.html
http://symfony.com/doc/current/cookbook/form/index.html
Something in between (see example below)
<?php
/**
* #Route("/customers", name="customers")
*
* #param Request $request
* #return Response
*/
public function index(Request $request)
{
$optionsResolver = new OptionsResolver();
$optionsResolver->setDefaults([
'email' => '',
'phone' => '',
]);
$filter = $optionsResolver->resolve($request->query->all());
/** #var CustomerRepository $customerRepository */
$customerRepository = $this->getDoctrine()->getRepository('AppBundle:Customer');
/** #var Customer[] $customers */
$customers = $customerRepository->findFilteredCustomers($filter);
return $this->render(':customers:index.html.twig', [
'customers' => $customers,
'filter' => $filter,
]);
}
More about OptionsResolver - http://symfony.com/doc/current/components/options_resolver.html
You can do it this:
$clientName = $request->request->get('appbundle_client')['clientName'];
Sometimes, when the attributes are protected, you can not have access to get the value for the common method of access:
(POST)
$clientName = $request->request->get('clientName');
(GET)
$clientName = $request->query->get('clientName');
(GENERIC)
$clientName = $request->get('clientName');
Most of the cases like getting query string or form parameters are covered in answers above.
When working with raw data, like a raw JSON string in the body that you would like to give as an argument to json_decode(), the method Request::getContent() can be used.
$content = $request->getContent();
Additional useful informations on HTTP requests in Symfony can be found on the HttpFoundation package's documentation.
For symfony 4 users:
$query = $request->query->get('query');
$request = Request::createFromGlobals();
$getParameter = $request->get('getParameter');
use Symfony\Component\HttpFoundation\Request;
public function indexAction(Request $request, $id) {
$post = $request->request->all();
$request->request->get('username');
}
Thanks , you can also use above code
#www.example/register/admin
/**
* #Route("/register/{role}", name="app_register", methods={"GET"})
*/
public function register(Request $request, $role): Response
{
echo $role ;
}
If you need getting the value from a select, you can use:
$form->get('nameSelect')->getClientData();
Try this, it works
$this->request = $this->container->get('request_stack')->getCurrentRequest();
Regards
public function indexAction(Request $request)
{
$data = $request->get('corresponding_arg');
// this also works
$data1 = $request->query->get('corresponding_arg1');
}