ZF2 Mock crashes on undefined method - unit-testing

I'm following this tutorial for unit testing on ZF2. I'm familiar with unit testing, so I pretty much understand what's going on.
I'm getting a PHP Fatal error: Call to undefined method Mock_AlbumTable_9fb22412::fetchAll() in [my controller's route here].
If I'm following correctly, the controller calls fetchAll on my mock object. The weird part is why is it undefined, if I declared it in the mock expectations.
My test code is exactly the same on the link provided, (Literally copy/pasted), and my AlbumTable class is also from the tutorial:
<?php
namespace Album\Model;
use Zend\Db\TableGateway\TableGateway;
class AlbumTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
// ... more code ...
}
What am I missing here?
Edit: visiting said controller's route from the web browser works, so it's not an issue with the AlbumTable class, at the very least.

You miss this line:
$albumTableMock=$this->getMockBuilder('Album\Model\AlbumTable')
->disableOriginalConstructor()
->setMethods(array('fetchAll')) // <- you miss this line
->getMock();

Related

trouble geting started with laravel testing and mockery

I'm trying to get started on unit testing with laravel and am trying to follow a couple of tutorials.
Alot of my controllers have been generated using Jeffrey Ways excellent generators and they appear to create their own tests so I thought it would be simple to get started.
I've installed mockery and sqlite - I've removed a lot of the tests from the folder for now so I can test one at a time but I'm having trouble with the first one that tests a create:
Here's my test:
<?php
use Mockery as m;
use Way\Tests\Factory;
class BooksTest extends TestCase {
public function __construct()
{
$this->mock = m::mock('Eloquent', 'Book');
$this->collection = m::mock('Illuminate\Database\Eloquent\Collection')->shouldDeferMissing();
}
public function setUp()
{
parent::setUp();
$this->attributes = Factory::book(['id' => 1]);
$this->app->instance('Book', $this->mock);
}
public function tearDown()
{
m::close();
}
public function testIndex()
{
$this->mock->shouldReceive('all')->once()->andReturn($this->collection);
$this->call('GET', 'books');
$this->assertViewHas('books');
}
public function testCreate()
{
$this->call('GET', 'books/create');
$this->assertResponseOk();
}
public function testStore()
{
$this->mock->shouldReceive('create')->once();
$this->validate(true);
$this->call('POST', 'books');
$this->assertRedirectedToRoute('books.index');
}
}
When I run phpunit I get lots of php messages around mockery - theres so much there I cant see the specifc error message
Is there a simple step I'm missing here in my set up??
I've added mockery to my composer.json and updated. I have not added anything to app.php in the config files - package didnt suggest I should or as a facade.
So I'm not sure, never having used it before whether mockery is installed correctly - although I assume it is. Was it necessary for me to add mockery to a laravel installation or is it part of a normal install?
Solved - definite PICNIC error
I needed to extend the buffer size of my command line to scroll back and see the error which identified the problem -
This is my first dip into testing so didnt quite expect the fail to go the way it did.
Tiny steps required

Extending PHPUnit_Framework_TestCase while using dataProviders

I'm fairly new to using PHPUnit and I'm trying to use it more effectively by using data providers. I can get data providers to work when writing a normal test case, however I find that I'm rewriting my setup code for across several testcases. So I'm trying to extend PHPUnit_Framework_TestCase with a BaseTestCase class that does all of my common setup. This works if I run simple test in a test case that extends my BaseTestCase class. However I can't seem to use #dataProvider when extending my BaseTestCase class.
So my setup is:
class BaseTestCase extends PHPUnit_Framework_TestCase{
public static function setUpBeforeClass(){
//do setup
//this is getting called and it works
}
}
class myTest extends BaseTestCase{
public function myBasicTest(){
//this works
$this->assertEquals(2, 1+1);
}
public function myProvider(){
return [
[1,1,2],
[1,2,3],
[1,4,5],
]
}
/**
* #dataProvider myProvider
*/
public function testMyProvider($a, $b, $result){
//this doesn't work, the provider never gets called
//this would normally work if I extended PHPUnit_Framework_TestCase
$this->assertEquals($result, $a+$b);
}
}
I know the providers get ran before any of the setup does so I'm wondering if PHPUnit doesn't know that the provider exists because of the inheritance. Either way, does anyone know if what I'm trying to do is possible this way or does PHPUnit have another way of accommodating these types of situations?
Thanks for your help,
Jordan
Your test function does not begin with the word 'test'.
public function test_myProviderTest($a, $b, $result){
This is actually a non issue. I had an incorrect constructor setup in my test file. A very frustrating oversight.

Grails pollution between integration and unit tests

I know there's a lot out there about this particular topic, however I can't quite find anyone who has stumbled across my issue, and hopefully someone can explain this to me.
I have a Domain where I use the injected grailsApplication's dynamic method 'isDomainClass' in the equals method:
#Override
public boolean equals(Object obj) {
if(!grailsApplication.isDomainClass(obj.getClass())) { return false }
...
}
This works fine, and to unit test this i do:
#Mock([MyDomain])
...
def mockGApp
void setUp() {
mockGApp = new Object()
mockGApp.metaClass.isDomainClass = { obj -> true }
}
...
void testSomething() {
def myDomain = new MyDomain()
myDomain.grailsApplication = mockGApp
....
}
And when I run this with test-app -unit (on command line or in STS) it passes just fine.
I then ave an integration test that uses that domain (no mocking this time) and that again runs fine when ran with test-app -integration (either on the command line or in STS)
However if i run 'test-app' so it does both at once, I get a MissingMethodException: no method signature isDomainClass exists with parameters (java.lang.Class) ... and all that jazz.
On investigating it with println's in the service I'm testing in the tests, in the integration portion of the testing, before the equals method of my domain class is called, I can quite happily call grailsApplication.isDomainClass() and get the desired affect. However when the code steps into the domain's equals function the isDomainClass() method no longer exists, despite the grailsApplication object referring to the same object which is referenced in the service and has the dynamically added method.
It appears that the dynamic methods that grails adds to this class are not being injected when its called within the domain's methods but are getting injected within the service. And more bizarrely this only happens if the integration tests follow the unit tests. If done separately, no problemo...
Where does this pollution stem from? IS there any way to solve it?
P.S. using Grails 2.1.0
You have to remove the class you modified from metaClassRegistry in the destroy method (i.e.after test case runs). See below:
#After
void destroy() {
GroovySystem.metaClassRegistry.removeMetaClass(MyDomain.class)
}

CakePHP test behaviour with mapped method

Whilst creating an OwnableBehavior I decided to use the $mapMethods property that is available. It is to map any method called isOwnedByXXX() to isOwnedBy() (The link for the documentation on this is here)
Here is my OwnableBehavior code:
class OwnableBehavior extends Model Behavior {
public $mapMethods = array('/isOwnedBy(\w+)/' => 'isOwnedBy');
public function isOwnedBy(Model $model, $type, $id, Model $userModel, $userId) {
// Method is currently empty
}
}
Here is the TestCase code:
class OwnableBehaviorTest extends CakeTestCase {
public function testIsOwned() {
$TestModel = new Avatar();
$TestModel->Behaviors->attach('Ownable');
$result = $TestModel->Behaviors->Ownable->isOwnedByUser(
$TestModel, 1, new User(), 1);
$this->assertTrue($result);
}
}
When I run the test I get this error:
Call to undefined method OwnableBehavior::isOwnedByUser()
If I change the method call to isOwnedBy($TestModel, 'user', 1, new User(), 1); this works, so it looks like for some reason the mapped methods aren't working during the unit test. I have tested the mapped methods in a controller and I get no errors.
I wondered if it was down to how I was loading the behaviour into the model. I couldn't find any documentation in the cookbook on how to properly test Behaviours like there is with Components, Helpers, etc... So I just used the same techniques that the Core Behaviour tests use (Found in Cake/Test/Case/Model/Behavior/).
I did think maybe it could have been down to the fact that I am overwriting the ModelBehavior::setup() method, but I tried adding parent::setup($model, $settings) at the start of the setup method and I still get the same error. I am not overwriting any of the other ModelBehavior methods.
I guess I could just use the OwnableBehavior::isOwnedBy() method, but I'd quite like to know if I could get the mapped methods to work during a unit test.
The solution I have found is replacing this line:
$result = $TestModel->Behaviors->Ownable->isOwnedByUser(...);
with:
$result = $TestModel->isOwnedByUser(...);
So it's just a case of using it more like you would in the application, calling the behaviour method directly from the model. I don't know if this ruins the idea of a unit test and makes it more into integration testing though.

How do you assert a generic method was called with Rhino Mocks?

I have the following test to verify that my repository is calling it's respective session (I've rewritten it to highlight the actual problem):
[Test]
public void Why_Does_This_Fail()
{
var objectUnderTest = new SomeGenericsProblem();
var fakeSession = MockRepository.GenerateMock<ISession>();
fakeSession.Expect(s => s.Query<SomeClass>());
objectUnderTest.NotWorking<SomeClass>();
fakeSession.AssertWasCalled(t => t.Query<SomeClass>());
}
but when I run the test I get this:
System.InvalidOperationException :
Invalid call, the last call has been
used or no call has been made (make
sure that you are calling a virtual
(C#) / Overridable (VB) method).(C#) / Overridable (VB) method).
Any ideas what I'm doing wrong here? The session that I'm mocking is an interface, so it has to be virtual/overridable.
I have a feeling it has something to do with the fact that my Query method is a generic, but I don't know any other way to express what I'm trying to test.
Also, If I remove the part that sets up the expectation (i.e. this line of code:)
fakeSession.Expect(s => s.Query<SomeClass>());
I get a different exception which is equally confusing to me:
System.InvalidOperationException : No
expectations were setup to be
verified, ensure that the method call
in the action is a virtual (C#) /
overridable (VB.Net) method calloverridable (VB.Net) method call
So I figured out what was wrong.
ISession comes from NHibernate, which I probably should have mentioned.
The reason why this is cruicialy important is because
session.Query<T>
(which is what I'm trying to mock), is an EXTENSION METHOD.
Rhino Mocks apparently does not have the capability of mocking extension methods, hence why it's giving me the weird error.
So hopefully I'll have saves someone else the time and agony I've gone through in trying to figure out why my test won't pass.
The only solution that I've read about for this is to actually change the design of the extension method (which I can't do because it's part of NHibernate), or to use a different mocking framework like TypeMock.
[Test]
public void Query_WhenCalled_CallsSessionQuery()
{
// arrange
var session = MockRepository.GenerateStub<ISession>();
var r = new Repository(session);
// act
r.Query<SomeClass>();
// assert
session.AssertWasCalled(s => s.Query<SomeClass>());
}