Error using Mockery/phpUnit in Laravel - php

I'm a novice developer trying to get a test suite started for an existing laravel app but I have not experience in testing. Right now I'm just trying to get some tests built out to get some confidence and experience to write more substantial tests. I'm trying to test a relationship on a model(I realize it's not a very sensible tests) and trying to create a mocked model object to do so(I also understand it's better to do this in memory in a sqlite db but the major goal here is to test the controllers but I don't know how to deal with the authentication issue there). I have the following simple, stupid test:
public function testFoo()
{
$lead = m::mock('Lead');
$this->mock->shouldReceive('program')->once();
$this->assertEquals($lead->program_id, $lead->program->id);
}
But I get the following error:
LeadTest::testFoo
BadMethodCallException: Received Mockery_0_Lead::getAttribute(), but no expectations were specified
I don't understand what this error is trying to tell me and I'm finding no help googling the issue or reading through the docs I can find.
I assume I'm not setting the expected return values but this is a pretty general test and it doesn't seem right to hard code expected return values. What am I missing here?
I'm just testing a Laravel relationship to make sure I have things set up/implemented correctly:
public function program()
{
return $this->belongsTo('Program');
}

The problem was that I was missing the expected return value. It should've been something like this:
$this->mock->shouldReceive('program')->once()->andReturn(someObjectOrValue);
And the assertion should've been something like:
$this->assertEquals(someObjectOrValue, $lead->program->id);
The Mockery docs are a lot more verbose than I originally thought. http://docs.mockery.io/en/latest/reference/expectations.html

Related

PHPUnit get good feedback from the test

this question for me is to found a way to improve my test. When i test my code, usually I use this code:
$this->assertContains('textExample', $client->getResponse()->getContent());
when the test get OK all is right, but when the test fail the feedback from phpunit is so heavy, because php unit echo to terminal all the page into have search the textExample.
I would filter $client->getResponse()->getContent()) and search textExample in the precise part of site where i search it (div, h2...) and not have that heavy feedback form phpunit.
I hope I was clear, if not i'll try to re-explain.
Why don't you use either tearDwon() or onNotSuccessfulTest() methods. This way you could handle the error and filter if you need.
For instance you could try something like this to start:
public function onNotSuccessfulTest($e) {
// inspect $e to get the information you need, for ie:
print_r(get_class_methods($e)); die();
parent::onNotSuccessfulTest($e);
}
Check here for more information.

phpunit is letting a test pass when it should fail

I'm following along with this Laracasts video https://laracasts.com/lessons/tdd-by-example
In the lesson we are creating a test in PHPunit for the store method on the SupportController
Here is what the test looks like so far.
public function test_submits_support_request_upon_form_submission()
{
$this->call('POST', 'support/store', ['name' => 'john']);
}
I do not have a rout yet that matched 'support/store'.
When I run this I get no falures. In the video, he got an error Synphoy\Component\HttpKernal\Exeception\NotFoundHttpException
This makes sense becase the route the test is trying to hit doesn't exist yet. I'm using Laravel 5 and he's using 4 in the video. Is there something I need to change in order to get this to work correctly?
It's entirely possible that Laravel 5 doesn't throw an exception when you call the call method -- even if it doesn't match a route. If a test method doesn't throw an exception, and contains no assertions, it will pass. Although, that said, depending on how you've configured phpunit it should be warning you that your test contains no assertions.
I'd start with
What does $this->call('POST', 'support/store', ['name' => 'john']); return?
Are you sure your test class is included in the run?
Are you sure the test runner runs your class?
Answer these, and I suspect an answer to your question will emerge.

laravel how to debug a RESTful controller

I have this controller
class APIV1CustomerController extends BaseController{
public function getIndex(){
return "super new look";
}
public function postRegister(){
return "you have entered "+Input::get('fullName')+" as fullName parameter and "+Input::get('mobileNumber')+" as mobileNumber parameter";
}
}
I am trying to call the register function from IOS, I have some problems with the returing data. Thus, I need to debug that function.
when I return just simple test like return "test", it works well from IOS. but when I return the code I showed to you, some problem accrues, I can solve the problem myself from the IOS side but I need to debug the postRegister to check some issues.
when I was using J2EE web service, I can simple print some data to the console in my eClipse that is why I am asking if there is any way to do that in laravel.
Thanks
I am using php storm IDE
This might be useful: https://github.com/mlanin/laravel-api-debugger
It's a laravel package specifically built for assisting with APIs.
this might be irrelevant, but i learned a lot from this article when debugging api and jquery back then. http://www.openlogic.com/wazi/bid/188084/jQuery-and-Ajax-Error-Detection-and-Handling.
the first step is to see if there's any functions in your IOS which will notify you when you have an error after the http call, so that you know you actually are getting an error, ex. 404, 500 etc. Because if you are getting 200, most likely you don't need more advanced debug tool other than print.
server log is another friend which is very helpful in these white screen case, it'll tell you the exact error when 500 error happens. Ex. last error I got on my server was telling me a class name is not found, although it runs fine in my local.

How to properly call a class while providing error reporting at the class-caller level

I am writing fresh code, as part of refactoring an older legacy codebase.
Specifically, I am writing a Device class that will be used to compute various specifications of a device.
Device class depends on device's model number and particle count and I can call it as $device = new Device($modelNumber, $particleCount);
Problem: since this class will go into existing legacy code, I have no direct influence on if this class will be called properly. For Device to work, it needs to have correct model number and correct particle count. If it does not receive the proper configuration data, internally device will not be initialized, and the class will not work. I think that I need to find a way to let the caller know that there was an error, in case an invalid configuration data was supplied. How do I structure this to be in line with object oriented principles?
Or, alternatively, do I need to concern myself with this? I think there is a principle that if you supply garbage, you get garbage back, aka my class only needs to work properly with proper data. If improper data is supplied, it can bake a cake instead, or do nothing (and possibly fail silently). Well, I am not sure if this principle will be great. I do need something to complain if supplied configuration data is bad.
Here is some code of what I am thinking:
$device = new Device($x, $y);
$device->getData();
The above will fail or produce bad or no data if $x or $y are outside of device specs. I don't know how to handle this failure. I also want to assume that $device is valid when I call getData() method, and I can't make that assumption.
or
$device = new Device($x, $y);
if ($device->isValid())
$device->getData();
else
blow_up("invalid device configuration supplied");
The above is better, but the caller has to now they are to call isValid() function. This also "waters down" my class. It has to do two things: 1) create device, 2) verify device configuration is valid.
I can create a DeviceChecker class that deals with configuration vefication. And maybe that's a solution. It bothers me a little that DeviceChecker will have to contain some part of the logic that is already in Device class.
Questions
what problem am I trying to solve here? Am I actually trying to design an error handling system in addition to my "simple class" issue? I think I probably am... Well, I don't have the luxury of doing this at the moment (legacy code base is huge). Is there anything I can do now that is perhaps localized to the pieces of code I touch? That something is what I am looking for with this question.
I think you need to use below code to verify your passed arguments in construct
class Device {
public function __constructor($modelNumber, $particleCount) {
if(!$this->isValid($modelNumber, $particleCount) {
return false; //or return any error
}
}
}
This will check the passed params are valid or not and create object based on that only, otherwise return false or any error.

Yii - CHttpRequesterror while functional unittesting in module

When I'm trying to execute a functional unittest of a module within my Yii code, I keep receiving the following error:
CException: CHttpRequest is unable to determine the request URI.
At first, I though it was because it couldn't find the module. However, If I change the url to a wrong one, I get a correct error,s tating it couldn't find the view.
This is how my testing code looks like
public function testViewControllerModule()
{
ob_start();
Yii::app()->runController('module/controller/view');
}
Any ideas on what I might be missing?
bool.devs answer works so far.
This blog post explains the origin of the exception pretty well:
http://mattmccormick.ca/2012/09/14/unit-testing-url-routes-in-yii-framework/
In my case, I generalized the solution and have set the following variables in /www/protected/tests/bootstrap.php:
...
$_SERVER['SCRIPT_FILENAME'] = 'index-test.php';
$_SERVER['SCRIPT_NAME'] = '/index-test.php';
$_SERVER['REQUEST_URI'] = 'index-test.php';
Yii::createWebApplication($config);
Consider using 'index-test.php' instead of 'index.php' because it contains the config 'test.php' which is responsible for fixtures and maybe other test relevated configurations.
If someone has better suggestions feel free to comment :)
Kind regards
I think it's because you haven't set any server variables, i.e $_SERVER and you might be doing something like this in your controller:
Yii::app()->request ....
So before you run your test, make sure you use a fixture for the server variables also. I think this should suffice for now:
$_SERVER=array(
'REQUEST_URI'=>'index.php', // the other fields should follow
);
However to run functional tests i would recommend using SeleniumRC, you won't have to do these workarounds then, and can simulate user clicks also, i think.
Read the initial guide to Functional Testing , read the selenium rc phpunit guide, and also the CWebTestCase documentation.
Notes: You might still have to use fixtures for some variables, and i don't have much experience in testing(which is bad), so i'm not very sure if i am completely correct about selenium.

Categories