PHPUnit has setup and tearDown events that run, respectively, before and after each test within a test case. In my specific scenario, I also want to run something like a testCaseSetup and testCaseTearDown. Is that possible?
Current solution looks like this:
<?php
class MyTestCase extends \PHPUnit_Framework_TestCase
{
public function __construct($name = NULL, array $data = array(), $dataName = '')
{
// My test case setup logic
parent::__construct($name, $data, $dataName);
}
public function __destruct()
{
// My test case tear down logic
}
}
But it seems far from optimal for the following reasons:
I have to redeclare PHPUnit_Framework_TestCase construct and redirect any arguments. IF PHPUnit constructor is changed on a version update, my test case will stop.
Probably PHPUnit_Framework_TestCase was not declared to be used like this.
I would like to know if there are better solutions. Any ideas?
Yes, there are special methods for that purpose: setUpBeforeClass and tearDownAfterClass.
class TemplateMethodsTest extends PHPUnit_Framework_TestCase
{
public static function setUpBeforeClass()
{
// do sth before the first test
}
public static function tearDownAfterClass()
{
// do sth after the last test
}
Related
I need to test method which looks like this, but my question is: How i should enter this method especially when i can not "mock" AbstractController, and without variable of AbstractController it would not work
public function add(\Queue\Controller\AbstractQueueController $task)
{
//Logic of method
}
You don't need to mock it. You already set it as a parameter, so this test is not about testing AbstractQueueController.
So, for example, if your function looks like this :
public function add(\Queue\Controller\AbstractQueueController $task)
{
$task->doSomething();
}
Then, in the test,AbstractQueueController should receive a call to doSomething method(), and then assert the result of that.
well i did something like that i made extended class
class addtest extends Queue\Controller\AbstractQueueController
{
public function task()
{
}
}
and then in my QueeuServiceTest extended by PHPUnit_framework_TestCase
i made testmethod
public function testadd()
{
$this->queueService->add(new addtest);
}
it covers code but i do not know it is good practice
I am trying to set up the simplest of tests in my controller but, as with most things Laravel, there are no decent tutorials to demonstrate the simple stuff.
I can run a simple test (in a file called UserControllerTest) like this:
public function testIndex()
{
$this->call('GET', 'users');
$this->assertViewHas('users');
}
This calls the /users route and passes in an array users.
I want to do the same with Mockery but how?
If I try this:
public function testIndex()
{
$this->mock->shouldReceive('users')->once();
$this->call('GET', 'users');
}
I get an error that "Static method Mockery_0_users::all does not exist on this mock object.
Why not? I am mocking User which extends Ardent and in turn extends Eloquent. Why does ::all not exist for the mock?
BTW, these are the set-up functions for Mockery:
public function setUp()
{
parent::setUp();
$this->mock = $this->mock('User');
}
public function mock($class)
{
$mock = Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
You can't directly mock an Eloquent class. Eloquent is not a Facade and your User model neither. There is a bit of magic in Laravel but you can't do things like that.
If you want to mock your User class, you have to inject it in the controller constructor. The repository pattern is a good approach if you want to do that. There is a lot of articles about this pattern and Laravel on Google.
Here some pieces of code to show you how it could look like :
class UserController extends BaseController {
public function __construct(UserRepositoryInterface $users)
{
$this->users = $users;
}
public function index()
{
$users = $this->users->all();
return View::make('user.index', compact('users'));
}
}
class UserControllerTest extends TestCase
{
public function testIndex()
{
$repository = m::mock('UserRepositoryInterface');
$repository->shouldReceive('all')->andReturn(new Collection(array(new User, new User)));
App::instance('UserRepositoryInterface', $repository);
$this->call('GET', 'users');
}
}
If it seems to be too much structuration for your project you can just call a real database in your tests and don't mock your model classes... In a classic project, it just works fine.
This function is part of a project called apiato.io you can use it to mock any class in Laravel, even facade, basically anything that can be resolved with the IoC, which is almost all classes if you are using proper dependency injection:
/**
* Mocking helper
*
* #param $class
*
* #return \Mockery\MockInterface
*/
public function mock($class)
{
$mock = Mockery::mock($class);
App::instance($class, $mock);
return $mock;
}
i got a question when i was unit testing my application. I Have a method that require a dependency but only that method need it so i thought to don't inject it by construct but initialize it with App::make() of the IoC container Class. But now how can i unit test that?
Let's say a short example for understand how you unit testing this function of example
class Example {
public function methodToTest()
{
$dependency = App::make('Dependency');
return $dependency->method('toTest');
}
}
Test
public function test_MethodToTest() {
$dependency = m::mock('Dependency');
$dependency->shouldReceive('method')->once()->with('toTest')->andReturn(true);
$class = new Example();
$this->assertTrue($class->methodToTest('toTest')); // does not work
}
You're almost there. Create an anonymous mock with the expectations that you need and then register that mock as the instance for Dependency and you should be good to go.
That would look something like this
public function test_MethodToTest() {
$dependency = m::mock();
$dependency->shouldReceive('method')->once()->with('toTest')->andReturn(true);
App::instance('Dependancy', $dependancy);
$class = new Example();
$this->assertTrue($class->methodToTest()); // should work
}
I would prefer to inject the dependency in Example classes constructor.
class Example{
/** #var Dependency */
private $dependency;
public function __construct(Dependency $dependency){
$this->dependency = $dependency;
}
public function methodToTest(){
return $this->dependency->method('toTest');
}
}
class Test{
public function test_MethodToTest(){
$mock = Mockery::mock(Dependency::class);
$mock->shouldReceive('method')->once()->with('toTest')->andReturn(true);
$class = new Example($mock);
$this->assertTrue($class->methodToTest());
}
}
In your controller, libraries you can then use IoC like this
$example = App::make(Example::class);
Im testing with PHPUnit and my test fails on a function. But i don't know why.
The function i want to mock:
public function subscribe($email)
{
$message = new SubscribeMessage();
$message->setEmailaddress($email);
$message->setLocale(Locale::getDefault());
$this->getAmqpProducer()->publish($message, 'newsletter-subscribe');
return true;
}
and my Unit test:
public function testSubscribeSendsAmqpMessage()
{
$email = 'email#email.nl';
$locale = 'nl';
$this->amqpProducerMock
->shouldReceive('publish')
->once()
->with(
\Mockery::on(
function ($message, $routingkey) use (&$publishedMessage) {
$publishedMessage = $message;
return $routingkey == 'newsletter-subscribe';
}
)
);
$this->service->subscribe($email, $locale);
}
but the test says:
Mockery\Exception\NoMatchingExpectationException : No matching handler found for AcsiRabbitMq\Producer\Producer::publish(AcsiNewsletter\RabbitMq\Message\SubscribeMessage, "newsletter-subscribe"). Either the method was unexpected or its arguments matched no expected argument list for this method
How can i fix my Unit test? Or how can i refactor my test?
You Mock the subscribe, not the internal publish. When you run the test and call ->subscribe, it will attempt to execute the code in the class. Therefore, it will try to run the subscribe() method, which you appear to have a strange reference to your Mock.
Normally, your test will mock the subscribe, so you can return a value for the assert test, which is hard coded.
You appear to have tried to mock the GetAmqpProducer() object that is in your regular code. You need to either be able to pass the mock object to be used into your class, or to be able to assign it.
Simplified Example:
class Email
{
private $MsgObject;
// Constructor Injection
public __construct(SubscribeMessage $MessageObject)
{
$this->MsgObject = $MessageObject;
...
}
// Setter Injection
public function SetSubscribeMessage(Subscribe $MessageObject)
{
$this->MsgObject = $MessageObject;
}
public function setEmailaddress($email)
{
$this->MsgObject->emailAddress = $email;
...
}
public function setLocale($Locale)
{
$this->MsgObject->Locale = $Locale;
...
}
...
}
Your class sample above has too many internal objects and dependencies to be tested as such, since the test will actually call these. You would use Dependency Injection to pass the objects with known state, and have them return properly.
Please note, I am not showing how to do this in Mockery, as I do not use it, but this simple example should help you understand what I am trying to express.
So a simple test might look like:
public function testSubscribeMessage()
{
$email = 'email#email.nl';
$this->Mock(
->shouldReceive('setEmailAddress')
->once()
->will_return($email)
);
$SubscribeMessage = new SubscribeMessage($this->Mock);
$SetEmail = $SubscribeMessage->setEmailAddress($email);
$this->assertEquals($email, $SetEmail);
}
Is it possible to add a class constant to a mock using PHPUnit?
Here an example:
class SomeTest extends PHPUnit_Framework_TestCase {
public function setUp() {
$mock = $this->getMock( 'SomeClass' );
// Here I'd like to add a constant to $mock; something like
// $mock::FOOBAR;
}
}
Does any of you know how can I get this behavious to work?
Thx!
This question has been around a while with no answers, but I ran into this same problem. This does not appear to be possible; however, there's at least one dirty work-around:
In your test file
<?php
class SomeClass {
const FOOBAR = 'foobar';
}
class SomeTest extends PHPUnit_Framework_TestCase {
public function setUp() {
$mock = $this->getMock( 'SomeClass' );
}
}
// tests
?>
Then, you use your mocked object for mocked functionality, and you use the class constant the same way you would have originally. For example:
// Call a method on mocked object
// (would need to add this method to your mock, of course)
$mock->doSomething();
// Use the constant
$fooBar = SomeClass::FOOBAR;
This is dirty, so I'm sure things could get pretty messed up if you're using some sort of autoloading that tries to load the actual SomeClass class, but this will work "fine" if you're not loading the original SomeClass.
I'm definitely interested to hear other solutions as well as get some feedback on just how dirty this really is.