How do I mock find method in laravel? - laravel-4

I am trying to write a unit test, and I need to be able to mock an internal call to App::make('ClassName')->find($x). However, when I try this:
$mock = $this->getMockBuilder('ClassName')->
setMethods(['find'])->
getMock();
$mock->method('find')->willReturn('test');
echo $mock->find(1);
I get a PHPUnit_Framework_MockObject_BadMethodCallException with no message describing the error. Looking ad xdebug trace, I see that it calls the mock::find method, then immediately calls spl_autoload_call to get the BadMethodCallException class.
Why is the find method failing? If I use a different method (e.g. findx), then it works perfectly. What is magic about find, and how can I fix it?

Related

WrappedAPIView.__name__ = func.__name__ . AttributeError: 'dict' object has no attribute '__name__'

I am in a little bit of a pickle.
I have multiple decorators wrapping my view functions. I want to test that view function using pytest and this means the decorators will also be executed. Now, in some of those decorators, I am making API calls to an external service and I do not want to make those API calls while running my test, what I am doing instead is to mock the response from those decorators. When I ran the test I got AttributeError: 'dict' object has no attribute '__name__' and pytest is pointing to the decorators.py file in the djangorestframework package as the source of the error. Any idea what I am doing wrong?
Views.py file
#api_view(['POST'])
#DecoratorClass.decorator_one
#DecoratorClass.decorator_two
#DecoratorClass.decorator_three
#DecoratorClass.decorator_four
#DecoratorClass.decorator_five
#DecoratorClass.decorator_six
#DecoratorClass.decorator_seven
def my_view_fun(request):
my_data = TenantService.create_tenant(request)
return ResponseManager.handle_response(message="sucessful", data=my_data.data, status=201)
This works perfectly with manual testing, I only get this problem when I am running the test with pytest.
I am making the external API calls in decorators three, four and five.
TL;DR:
How can I handle the decorators wrapped around a view function when testing that view function in a situation where some of those decorators are making external API calls which should ideally be mocked in a test.

How can I use cache tags whith a mocked Cache in phpunit tests?

I have implemented Cache tags on a laravel project and I have something like this in my controller :
if (Cache::tags(['api'])->has('someKey')) {
return new JsonResponse(Cache::tags(['api'])->get('someKey'));
}
I would like to write a phpunit test to test this code : I mocked the Cache like found in the laravel documentation, but I haven't found anything on how to use tags on a mocked cache
I tried :
Cache::tags(['api'])->shouldReceive('has')->with('someKey')->andReturn(true)->once();
or
Cache::shouldReceive('has')->tags(['api'])->with('someKey')->andReturn(true)->once();
But none of this works, I got Call to undefined method Illuminate\Cache\ArrayStore::shouldReceive() or
call_user_func_array() expects parameter 1 to be a valid callback, class 'Mockery\Expectation' does not have a method 'tags'
Does anybody have a clue ? thanks a lot :)
You will need to mock tags call by itself and use ->andReturnSelf() to be able to make the mock chain. So calling Cache::tags(['api']) returns the mock instance.
Cache::shouldReceive('tags')->with(['api'])->andReturnSelf();
Cache::shouldReceive('has')->once()->with('someKey')->andReturn(true);
Cache::shouldReceive('get')->once()->with('someKey')->andReturn('result');

View::make in Phpunit

I've a function that returns a View::make($string). I want to test that this function did indeed return an instance of View object. $string points to a file that does exist.
When I try to run this function within Phpunit it doesn't seem to finish. How can I test in Phpunit that a View object was created?
Laravel has helper methods specifically designed for testing views.
Some of them include:
$response = $this->get('/path/to-your-route');
$response->assertViewIs($value);
$response->assertViewHas($key, $value = null);
$response->assertViewHasAll(array $data);
$response->assertViewMissing($key);
More info can be found here: https://laravel.com/docs/5.5/http-tests#available-assertions
If you need to assert that something is an instance of something else, you can try the following:
$this->assertInstanceOf($expected, $actual);
When you provide invalid string the view object will not be created and will throw an exception. Not sure what you have in your function that prevents the exception, but the way to go around this issue, is to include this line in the failing test:
$this->expectException(InvalidArgumentException::class);
The issue stemmed down from usage of var_dump as I wanted to see the object in question. As nothing was presented in output, I assumed that had to do with View::make rather than outputting the object to the console.

is laravel cloning my mock object?

Im testing a Soap web service with getMockFromWsdl from phpunit, for unit testing within laravel works fine, but when I try to replace the SoapClient in a feature test, it always fails, like the web service never called, but actually the mock is called.
I suspect that laravel is cloning somewhere my $this->soapClient because if I debug the code, it calls the soap mock and gets what is faked in the mock but always receive the error:
Expectation failed for method name is equal to <string:GetToken> when invoked at least once.
Expected invocation at least once but it never occurred.
My code is like:
public function test_soap_call()
{
$this->soapClient = $this->getMockFromWsdl(dirname(__FILE__).'/../Mocks/service.wsdl');
$this->soapClient->expects($this->atLeastOnce())
->method('GetToken')
->with(['Code' => '03600', 'User' => 'username'])
->willReturn(unserialize('O:8:"stdClass":1:{s:26:"GetTokenResult";s:36:"5aae60ec-2bcd-459d-a135-a20eb7c10007";}'));
$this->app->instance('MySoapClient', $this->soapClient);
$this->postJson('/api/order', $this->getValidRequest());
}
and in my controller (/api/order) I have
$soap = $this->app->make('MySoapClient');
$soap->GetToken(['Code' => '03600', 'User' => 'username']);
Am I using correctly the Laravel Service Container?
PD: Something similar happened to me, when doing a Spy and using $app->instance, where I was trying to get what was passed to an object, but always got null. I solved it declaring the field of the spy static.
Check this from php.net:
http://php.net/manual/en/language.oop5.references.php
... "objects are passed by references by default". This is not completely true. ...

Rally API using Ruby: How do I reference the testcase method (Automated/Manual)?

I am using Ruby to work with the Rally API. I am trying to reference the testcase method. The method being Manual or Automated, but I always get an error. I am using Ruby, so I don’t know if method is a reserved word in Ruby, or what is happening. Could you please let me know how to reference the test case method?
I am able to do:
testcase.objective
testcase.priority
etc.
But I can’t do
testcase.method
I always get this error.
‘method’: wrong number of arguments (0 for 1) (ArgumentError)
Are you using rally_rest_api or rally_api?
If you are using rally_rest_api - Charles is correct. try testcase.elements[:method]
(fieldname downcased and underscored as a symbol)
If you are using rally_api - http://rubygems.org/gems/rally_api -
Getting fields can just be:
testcase["FieldName"]
Hope that helps.
You just need to capitalize the names when trying to access built-in fields (i.e. fields that are not custom). I came across this problem myself and using tc.Method instead of tc.method fixed it.
The reason this error shows up can be seen in the docs for Object#method which, as you've likely figured out by now, causes your code to call the method method instead of access the field named method.

Resources