I'm starting to look into testing so thought id do something simple like see if a page loads correctly.
Here is my test;
<?php
use App\Users\Models\User;
class BlogPostsTest extends TestCase {
protected $baseUrl = 'http://localhost:8000';
public function testBlogPostsAreAccessible()
{
$this->be( User::findOrFail(1) );
$response = $this->call( 'GET', '/admin/blog-posts' );
$this->assertEquals( 200, $response->getStatusCode() );
}
}
Which returns and error
1) BlogPostsTest::testBlogPostsAreAccessible Error: Call to undefined
method
Symfony\Component\Debug\Exception\FatalThrowableError::getStatusCode()
/Users/ss/git/modules/admin/admin-blog/app/Exceptions/Handler.php:77
/Users/ss/git/modules/admin/admin-blog/app/Exceptions/Handler.php:58
/Users/ss/git/modules/admin/admin-blog/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:291
/Users/ss/git/modules/admin/admin-blog/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:107
/Users/ss/git/modules/admin/admin-blog/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:515
/Users/ss/git/modules/admin/admin-blog/tests/ExampleTest.php:12
FAILURES! Tests: 1, Assertions: 0, Errors: 1.
The error is coming from $this->call() does anyone know why this is?
regards
Are you sure your 'admin/blog-posts' returns an actual response object? Can you dd() the output in your test? So:
dd($response);
To see what it is your code is returning?
Related
Disclaimer: I'm totally new to Haxe, but I have experience in many other languages.
I have tests similar to the following:
function doTest(type:SomethingMagic, tests:Array<Array<Int>>) {
for (t in tests) {
var res = DoSomeMagicalWork(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]);
assertEquals(type, res.type);
}
}
The problem with this is that the unit test framework, when run on many different arrays, doesn't give me the correct line for which the test failed. In other words, if I'm running this method with a bunch of arrays, like:
doTest(SOME_MAGIC_TYPE,
[[0, 0, 0, 1625, 0, 35, 0, 0, 0, 0, 0],
...
]);
and one of these lines fails, it doesn't tell me which line failed. Now, I know that I could probably restructure these tests to be a bit more intuitive anyway, but this was written by someone else, and I don't have the ability to change each of these at the moment.
What I'd like to do is the following:
function doTest(type:SomethingMagic, tests:Array<Array<Int>>) {
var number = 0;
for (t in tests) {
var res = DoSomeMagicalWork(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]);
assertEquals(type, res.type, "Test #" + number + " for type " + type);
number++;
}
}
So, basically, I'd like to be able to pass in some extra messaging information to the assertEquals function, similar to what one can do in other unit testing frameworks. Then, upon failure, it would output the standard assertion message, possibly appended by the additional message I sent as a parameter to the function. Originally, I thought it was as simple as sub-classing haxe.TestCase, but that doesn't appear to be quite as simple as I thought, due to the way Haxe interprets types (apparently).
Has anyone had success with something similar to this that could give me a recommendation on how to accomplish it?
If you want to only get the position of the error you can use haxe.PosInfos as the last argument of your doTest() function and pass that arguemnt to assertEquals() like this:
import haxe.unit.TestCase;
class Main {
static function main() {
var r = new haxe.unit.TestRunner();
r.add(new Test());
r.run();
}
}
class Test extends TestCase {
public function new() {
super();
}
public function testExample() {
doTest(1, 1);
doTest(1, 2);
doTest(3, 3);
}
function doTest(a:Int, b:Int, ?pos:haxe.PosInfos) {
assertEquals(a, b, pos);
}
}
Online example here
It will give you the position that called doTest() in the error:
Test::testExample() ERR: Main.hx:18(Test.testExample) - expected '1' but was '2'
Another option if you want to add a custom message is to catch the assertEquals() error and rethrow the currentTest with a custom error like this:
import haxe.unit.TestCase;
class Main {
static function main() {
var r = new haxe.unit.TestRunner();
r.add(new Test());
r.run();
}
}
class Test extends TestCase {
public function new() {
super();
}
public function testExample() {
doTest(1, 1, "Error on test 1");
doTest(1, 2, "Error on test 2");
doTest(3, 3, "Error on test 3");
}
function doTest(a:Int, b:Int, errorMsg:String, ?pos:haxe.PosInfos) {
try {
assertEquals(a, b, pos);
} catch(e:Dynamic) {
currentTest.error = errorMsg;
throw currentTest;
}
}
}
Online example here
Which will give you the following error:
Test::testExample() ERR: Main.hx:18(Test.testExample) - Error on test 2
You are effectively blending multiple tests into a single one. And Haxe cannot tell where your array element is defined (line number, etc)
What I suggest is to change the signature of doTest to accept Array<Int> instead of Array<Array<Int>> and call doTest multiple times instead of just once. Together with the suggestion from Justo, passing the pos object to assetEquals, you will get the position correctly.
I'm trying to write white test to test my API with file uploads.
I'm following the docs about this using basic client request, not crawler.
The unit test is:
class RecordsControllerTest extends WebTestCase {
private $client;
public function __construct() {
parent::__construct();
$this->client = self::createClient();
$this->client->insulate();
}
public function testApiPostUpload($params){
$fileToUpload = realpath(__DIR__.'/../../resources/mpthreetest.mp3');
$file = new UploadedFile(
$fileToUpload,
'mpthreetest.mp3',
MimeTypeGuesser::getInstance()->guess($fileToUpload),
filesize($fileToUpload)
);
$this->client->request('POST', '/records/'.$params['createdRecordId'].'/upload', array(), array('file' => $file) );
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
}
}
When I execute the test I receive an error:
Exception: Serialization of 'Symfony\Component\HttpFoundation\File\UploadedFile' is not allowed
/path/to/project/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Client.php:165
/path/to/project/vendor/symfony/symfony/src/Symfony/Component/BrowserKit/Client.php:348
/path/to/project/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Client.php:143
/path/to/project/vendor/symfony/symfony/src/Symfony/Component/BrowserKit/Client.php:313
/path/to/project/src/Bundle/Tests/Functional/Controller/RecordsControllerTest.php:182
I have found this question for about the same error, but in this case the request is not sent to the controller and the problem is not the entity and implementing serialization.
Anyone who knows how to fix this?
Anyone who managed to make unit test for uploading file in symfony 2?
You could try to NOT insulate the requests passing false as argument to the insulate method so try this:
$this->client->insulate(false);
instead of this:
$this->client->insulate();
Hope this help
I was able to resolve it by setting the changeHistory parameter to false (7th and last parameter in the request method signature):
$crawler = $client->request($form->getMethod(), $form->getUri(), $values, $files, [], null, false);
This will prevent the serialize on following lines :
if ($this->followRedirects && $this->redirect) {
$this->redirects[serialize($this->history->current())] = true;
return $this->crawler = $this->followRedirect();
}
I'm testing my Rest APIs.
I want to pass a parameter to my request.
This is in my controller, I have:
public function index(Request $request)
{
$abuse = Abuse::where('bombId', $request->input('bombId'))->get();
}
Thing is with PhpUnit, I can never simulate the bombId parameter...
Here is my code:
$data['bombId'] = 25; // I also tried $bombId = 25;
$this->get('api/v1/abuse', $data])
->seeJson(['total' => 11]);
$this->assertResponseStatus(200);
EDIT:
When I use:
$this->call('GET','api/v1/abuse', $credentials);
Param is passed, but I can't use anymore SeeJson method :(
Any Idea?
I found my answer with Jeffrey Way:
$response = $this->call('GET', 'api/v1/abuse', $credentials);
$data = $this->parseJson($response);
$this->assertIsJson($data);
$this->assertEquals(11, $data->total);
I am attempting to test a simple Laravel model which has required "password" and "email" properties. My test reads as follows…
public function testEmailIsRequired() {
$user = new User;
$user->password = 'derp';
// should not save
$this->assertFalse($user->save());
}
Rather than correctly agree that "this doesn't work" and a successful test, I’m getting…
1) UserTest::testEmailIsRequired
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation:
19 NOT NULL constraint failed: users.email
(SQL: insert into "users" ("password", "updated_at", "created_at")
values (derp, 2014-09-26 15:27:07, 2014-09-26 15:27:07))
[...]
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
I’m afraid that I’m a total novice here. It seems to me that PHPUnit ought to be suppressing the database driver’s own error reporting and just accepting "false"… help?
Your test is looking for the function to return false. Any other errors generated in your function will still be returned, since you are calling the function.
public function testEmailIsRequired()
{
$user = new User;
$user->password = 'derp';
// should not save
$this->assertFalse($user->save());
}
public function testMockSaveWorks()
{
$Mock = $this->getMock('User', array('save'));
// Set up the expectation for the getResult() method
$Mock->expects($this->any())
->method('save')
->will($this->returnValue(true));
$this->assertTrue($Mock->save());
}
class User()
{
...
public function save()
{
if( is_null($this->email) )
return false;
...
return true;
}
}
You should then use Mocks to remove the actual save() function and its tie in to your database, and have the mock return true to pretend to save the record to show that you have tested the module.
I get a 'parameter count mismatch' TargetParameterCountException when I want to test my Tenant repository:
The interface:
public interface ITenantRepository
{
IQueryable<Tenant> Get(Expression<Func<Tenant, bool>> filter = null,
Func<IQueryable<Tenant>, IOrderedQueryable<Tenant>> orderBy = null,
string includeProperties = null);
}
The test code:
var TenantRepository = new Mock<ITenantRepository>();
TenantRepository
.Setup(p => p.Get(It.IsAny<Expression<Func<Tenant, bool>>>(),
It.IsAny<Func<IQueryable<Tenant>,IOrderedQueryable<Tenant>>>() ,
It.IsAny<string>()))
.Returns(new Func<Expression<Func<Tenant, bool>>,
IQueryable<Tenant>>(expr => Tenants.Where(expr.Compile()).AsQueryable()));
Tenant TestTenant = TenantRepository.Object.Get(
t => t.TenantID == Tenant2.TenantID,
null,
null).FirstOrDefault();
The error occurs on the last line.
Found the solution for the correct parameters:
TenantRepository.Setup(p => p.Get(It.IsAny<Expression<Func<Tenant, bool>>>(),
It.IsAny<Func<IQueryable<Tenant>, IOrderedQueryable<Tenant>>>(),
It.IsAny<string>()))
.Returns(
(Expression<Func<Tenant, bool>> expr,
Func<IQueryable<Tenant>, IOrderedQueryable<Tenant>> orderBy,
string includeProperties) => Tenants.Where(expr.Compile()).AsQueryable());
I believe the problem resides in the return type of your mocked object: according to your interface, the method Get should return an IQueryable, but you are mocking it to return a Func<Expression<Func<Tenant, bool>>, IQueryable<Tenant>> instead.
Just keep in mind that returning a function is different from returning its result; in this case, you should create an expected IQueryable object and just tell Moq to return it. It doesn't make much sense to mock something using its expected behaviour - which looks like what you are trying to do here.