How to mock file system with Laravel and vfsStream? [Laravel 5.1] - unit-testing

I have request like this:
$path = storage_path('testing/unnamed.png');
$original_name = 'unnamed';
$mime_type = 'image/png';
$size = 2192;
$error = null;
$test = true;
$file = new UploadedFile($path, $original_name, $mime_type, $size, $error, $test);
$response = $this->call('POST', 'games', [
'name' => 'TEST321',
'category' => 'test',], [], ['picture' => $file], []);
And insted of storing image how can I mock file system?
Also this don't pass laravel mime validation mimes:jpeg,bmp,png... Anyone know how to fix it?

laravel allows you to mock any facade by calling the 'shouldReceive' mockery method on it:
File::shouldReceive('move')
->with('arguments');
see the docs for more information

I wrote and use a Laravel 5.4 package, https://packagist.org/packages/stechstudio/laravel-vfs-adapter to let me easily switch to a Virtual File System adapter.

Related

Stubbing/mocking a service in a Dancer2 application

Usually, I have a setup similar to this:
#!/usr/bin/env perl
package Demo;
use Dancer2;
use Moose;
sub get($self, $params) {
my $whatever = ...; # connect with db and do stuff
return $whatever;
}
my $service = Demo->new();
sub make_web_friendly($param) { # no $self, here!
return "Hello $param!";
}
get '/' => sub {
my $response = $service->get(query_parameters);
return make_web_friendly($response);
};
start;
This way, I can separate concerns pretty well and my services are testable without going over a bogus web request via Plack::Test;
However, whenever I test the request, I always also test the service, with goes against this separation.
I would want to provide the Plack Test with a stubbed service that would mock a service answer. So (I assume) either I can make the get action somehow $self-aware, or would have to pass the mocked service to Plack.
# this is put together to showcase the principle, it does not work
package Stub {
use Moose;
use Test::More;
use Data::Dumper;
sub get($self, $params) {
diag "I received:" . Dumper($params);
return "Bianca!";
}
}
my $app = Demo->to_app;
my $test = Plack::Test->create($app);
my $stub = Stub->new();
$test->service($stub);
my $request = HTTP::Request->new( GET => '/' );
my $response = $test->request($request);
is $response, 'Hello, Bianca', 'Bianca was here';
How can I achieve (something like) this?

How can I test a Yii2 model in a library project?

I'm trying to implement an adapter that is using a Yii model object extending yii\db\ActiveRecord. The object is passed as constructor arg to the adapter class.
My issue is now that I still couldn't figure out how to get this to work properly. I've even tried mocking it but got stuck because Yii is using lots of static methods to get it's objects. Sure, I could now try to mock them... But there must be a better way?
public function testSuccessFullFind(): void
{
$connection = (new Connection([
'dsn' => 'sqlite:test'
]))
->open();
$queryBuilder = new \yii\db\sqlite\QueryBuilder($connection);
$app = $this->createMock(Application::class);
\Yii::$app = $app;
$app->expects($this->any())
->method('getDb')
->willReturn($this->returnValue($connection));
$userModel = new UserModel();
$resovler = new Yii2Resolver($userModel);
$result = $resolver->find(['username' => 'test', 'password' => 'test']);
// TBD asserts for the result
}
The UserModel is used to find a user record internally.
This results in:
1) Authentication\Test\Identifier\Resolver\Yii2ResolverTest::testSuccessFullFind
Error: Call to a member function getDb() on null
vendor\yiisoft\yii2-dev\framework\db\ActiveRecord.php:135
vendor\yiisoft\yii2-dev\framework\db\ActiveQuery.php:312
vendor\yiisoft\yii2-dev\framework\db\Query.php:237
vendor\yiisoft\yii2-dev\framework\db\ActiveQuery.php:133
tests\TestCase\Identifier\Resolver\Yii2ResolverTest.php:31
The code above is obviously the WIP of a test case.
So how can I configure a test connection and get my ActiveRecord object to use it?
You can pass connection as argument of all() method:
$results = UserModel::find()->where(['id' => 1])->all($connection);

Test JSON-returning controller method without MissingViewError

I am testing a Controller method that has only a JSON view. My method runs as expected, but the test method only returns "MissingViewException". Is there a solution to avoiding this exception in the unit test (besides inserting an empty file at View/People/map_leads.ctp)?
PeopleController.php
public function mapLeads($territory_id = null) {
$leads = $this->Person->getPeople([
'territory_id' => $territory_id
]);
$this->set('leads', $leads);
}
AppController.php
public $components = ['RequestHandler'];
routes.php
Router::parseExtensions('json');
PeopleControllerTest.php
public function testMapLeads() {
$id = 40;
$result = $this->testAction('/people/mapLeads/' . $id, array('return' => 'vars'));
}
View/People/json/map_leads.ctp exists and is properly utilized by CakePHP; it is only the test that wants to see View/People/map_leads.ctp.
I checked at CakePHP: calling testAction to a json-returning method causes missing view exception reminding about adding RequestHandler to $components. This does not resolve the exception.
You aren't issuing a JSON request/accessing a JSON endpoint, as neither your request URL does contain the .json extension, nor does your request send an appropriate Accept header (I don't remember whether the latter is possible with the 2.x controller test case class at all).
Use the .json extension and you should be good.
$this->testAction('/people/mapLeads/' . $id . '.json', array('return' => 'vars'));
Write this code inside your action.
$this->autoLayout = false;
$this->autoRender = false;
$this->response->type('application/javascript');

Delete fixtures after load using Fixtures

I'm working in some tests for my code and I get my first "STOP" since I don't know how to mover forward on this. See in my setUp() function I load fixtures:
public function setUp() {
static::$kernel = static::createKernel();
static::$kernel->boot();
$this->em = static::$kernel->getContainer()->get('doctrine')->getManager();
$this->user = $this->createUser();
$fix = new MetaDetailGroupFixtures();
$fix->load($this->em);
parent::setUp();
}
But then I have remove that created data since I have a test for the bad case (when not entities are returned):
public function testListMetaDetailGroupFailAction() {
$client = static::createClient();
$this->logIn($client, $this->user);
$route = $client->getContainer()->get('router')->generate('meta-detail-group-list', array('parent_id' => 20000), false);
$client->request("GET", $route);
$decoded = json_decode($client->getResponse()->getContent(), true);
$this->assertCount(0, $decoded['entities']);
$this->assertArrayHasKey('success', $decoded);
$this->assertJsonStringEqualsJsonString(json_encode(array("success" => false, "message" => "No existen grupos de metadetalles de productos creados")), $client->getResponse()->getContent());
$this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertSame('application/json', $client->getResponse()->headers->get('Content-Type'));
$this->assertNotEmpty($client->getResponse()->getContent());
}
Since records are created in setup and they remain in DB that test fail. Any advice on this? How did yours solve that?
There is no easy way to do what you ask. What is normally done is truncating the database before and after executing your tests so you have a truly clean and isolated environment.
Quoting from this nice article (http://blog.sznapka.pl/fully-isolated-tests-in-symfony2/:
public function setUp()
{
$kernel = new \AppKernel("test", true);
$kernel->boot();
$this->_application = new \Symfony\Bundle\FrameworkBundle\Console\Application($kernel);
$this->_application->setAutoExit(false);
$this->runConsole("doctrine:schema:drop", array("--force" => true));
$this->runConsole("doctrine:schema:create");
$this->runConsole("doctrine:fixtures:load", array("--fixtures" => __DIR__ . "/../DataFixtures"));
}
As you can see, this solution makes use of Doctrine's Symfony2 commands in order to achieve the isolation state. There is a bundle I like to use which solves exactly this problem and let you use nice ready to use FunctionalTest base classes and many other features. Check it out:
https://github.com/liip/LiipFunctionalTestBundle

Building a web service with Perl

I need to build a server-side application (tiny web service) for testing proposes. What are some CPAN modules and Perl libraries for implementing such task?
Testing a tiny Web service with Plack::Test:
use Plack::Test;
use Test::More;
test_psgi(
app => sub {
my ($env) = #_;
return [200, ['Content-Type' => 'text/plain'], ["Hello World"]],
},
client => sub {
my ($cb) = #_;
my $req = HTTP::Request->new(GET => "http://localhost/hello");
my $res = $cb->($req);
like $res->content, qr/Hello World/;
},
);
done_testing;
There are a lot of possibilities
CGI - if you like to do everything like in the olden days
CGI::Application - a little more advanced
or you could use frameworks like
Catalyst
Dancer
Mojolicious
It depends on your skills and aims what solution you should choose.
A web service simply returns a HTTP status code and some data, perhaps serialized in JSON or XML. You can use the CGI module to do this, e.g.:
#!/usr/bin/perl -w
use strict;
use warnings;
use CGI;
use CGI::Pretty qw/:standard/;
use URI::Escape;
my $query = CGI->new;
my $jsonQueryValue = uri_unescape $query->param('helloWorld');
# let's say that 'helloWorld' is a uri_escape()-ed POST variable
# that contains the JSON object { 'hello' : 'world' }
print header(-type => "application/json", -status => "200 OK");
print "$jsonQueryValue";
You can, of course, print an HTTP response with other status codes and data. A web service might need to return a 404 error, for example, depending on what's being asked for. That sort of thing.
I like to use mojolicious. It's lightweight at first and can do the heavy lifting later too. Mojolicious::Lite in particular is good for quick and dirty.
use Mojolicious::Lite;
# Route with placeholder
get '/:foo' => sub {
my $self = shift;
my $foo = $self->param('foo');
$self->render(text => "Hello from $foo.");
};
# Start the Mojolicious command system
app->start;