Feature test phpunit lib #2794

Closed
wants to merge 25 commits into
from

Projects

None yet

9 participants

@blanchonvincent
Contributor

Feature to test your controllers (http or console router).

See use case here : https://github.com/blanchonvincent/zend-framework-test-phpunit
Integration in a project : https://github.com/blanchonvincent/au-coeur-de-zend-framework-2/tree/master/tests

@bakura10
Contributor

Could you add docblock for everything (function return and co...) as it would help a lot for IDE ;-).

I'll read it more carefully tonight, but as I told you, this is a very good idea and should be integrated to 2.1 I suppose :).

@juriansluiman
Contributor

I think the idea behind this is very good.

The only real big problem I have now with the setup is the link to the application configuration. You cannot rely on __DIR__ . '/../../../config/application.config.php'. What if I make the module composer enabled and it resides in vendor/my-name/my-module. Or when I start developing it, it's in module/my-module. Perhaps I have a shared module repository on my system, so the module is in /usr/local/share/zf2/module/my-module.

There must be something you can test modules in separation, for example you say "generate an application config where you enable module MyModule". Like you do now hard-coded with the Mock module, but then variable. You should think about how to handle dependencies from MyModule then (and where they are located), but it's a vital point for testing all your modules!

I will look more thoroughly at the code at a later moment, but it'd be good if there is a solution for above problem.

@blanchonvincent
Contributor

You can write your own file "application.config.php" for tests and test only one or several module, not a problem.
For the dependencies, you can create tests with modules deactivated to test the dependencies.

@blanchonvincent
Contributor

Look my new commit : https://github.com/blanchonvincent/zf2/blob/f656178cc92b1b98ff199543772291588f533e67/tests/ZendTest/Test/PHPUnit/Controller/ModuleDependenciesTest.php.

You can now :

public function testBadDependenciesModules()
{
    $this->setApplicationConfig(
        include __DIR__ . '/_files/application.config.with.dependencies.disabled.php'
    );
    $sm = $this->getApplicationServiceLocator();
    $this->assertEquals(false, $sm->has('FooObject'));
    $this->assertEquals(true, $sm->has('BarObject'));

    $this->assertNotModulesLoaded(array('Foo'));
    $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException');
    $this->assertNotModulesLoaded(array('Foo', 'Bar'));
}

I think it's a part of answer to your question. Read the code and you will look how it's flexible :)

@Thinkscape
Member

Oh oh oh! Brilliant idea!
Thank you Vincent.

I agree with @bakura10 though - we need docbocks for all assert* functions so there are no second thoughts on what does what.

@blanchonvincent
Contributor

@Thinkscape @bakura10 docblocks added :)

@Thinkscape
Member

You rock @blanchonvincent ;)

@weierophinney weierophinney commented on an outdated diff Oct 30, 2012
...d/Test/PHPUnit/Mvc/Service/ServiceListenerFactory.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Zend\Test\PHPUnit\Mvc\Service;
+
+use Zend\Mvc\Service\ServiceListenerFactory as BaseServiceListenerFactory;
+
+class ServiceListenerFactory extends BaseServiceListenerFactory
+{
@weierophinney
weierophinney Oct 30, 2012 Member

This class looks problematic, as it can easily go out-of-date with the base ServiceListenerFactory.

@weierophinney
Member

This is clearly an analog of what we had in ZF1.

TBH, I was hoping to avoid any such thing in ZF2. Because controllers are expected to return something, you typically should be able to simply do assertions on the return values.

That said, there's probably a place for functional testing. My only issue is that it may give a false sense of confidence. With ZF1, you controllers were basically limited to your application -- they wouldn't usually live anywhere else. With controllers now part of modules that could be used in a multitude of situations, having passing functional tests doesn't mean much, as the environment in which they are used could change a ton based on where the module is installed and how it's configured.

I'm not saying I won't merge this -- just wanting to share my hesitation with recommending a pattern like this.

@blanchonvincent
Contributor

Ok i understand your opinion.

For me i had 2 ideas :

keep the possibility to test application like a customer (with the http client)
keep same method like zf1, the methods are very easy to understand and simple to implements.

Why i write that ?
At my job, we test each modules separately, because, like you say, modules could be used in a multitude of situations. But after write tests in each modules, there are not functional testing, and how i can to certify at my team that can try the web app with no side effects ? i think functional testing can not replace the tests in each modules.

The advantage with this lib is that i can tests modules with the configuration which deployed on my front server & back server. The only "problem" is on ServiceListenerFactory which must be updated when the ServiceListenerFactory is updated, but it's necessary.

@weierophinney
Member

@blanchonvincent Excellent -- I was fishing for your rationale, and it makes great sense. :) Can you respond to the question I had on the test-specific service listener as well? After that's cleared up, I think we can review for merge. I'll also need docs from you at some point. :)

@Thinkscape
Member

There's case for functional testing, but also internal integration tests
which include controllers that interact with multiple modules, mvc
listeners, view layer, plugins etc. A complex request might go through
multiple facilities before producing final result, which can only be
reliably tested while having all pieces of the puzzle present.

It's a very useful testing layer between decoupled unit tests (for each
component) and high-level automated functional tests (I.e. with JavaScript
clicking buttons, simulating real user, submitting forms, etc.)

A.

On Oct 30, 2012, at 20:20, weierophinney notifications@github.com wrote:

This is clearly an analog of what we had in ZF1.

TBH, I was hoping to avoid any such thing in ZF2. Because controllers are
expected to return something, you typically should be able to simply do
assertions on the return values.

That said, there's probably a place for functional testing. My only issue
is that it may give a false sense of confidence. With ZF1, you controllers
were basically limited to your application -- they wouldn't usually live
anywhere else. With controllers now part of modules that could be used in a
multitude of situations, having passing functional tests doesn't mean much,
as the environment in which they are used could change a ton based on where
the module is installed and how it's configured.

I'm not saying I won't merge this -- just wanting to share my hesitation
with recommending a pattern like this.


Reply to this email directly or view it on
GitHubhttps://github.com/zendframework/zf2/pull/2794#issuecomment-9919346.

@weierophinney
Member

@Thinkscape Yeah, @blanchonvincent gave a compelling argument already. :)

@texdc
Contributor
texdc commented Nov 6, 2012

I approve of this feature. Could you also provide examples of using it to test MvcEvent and Application event listeners? Thanks!

@trondal
trondal commented Nov 6, 2012

I found your hardcoding of localhost in AbstractControllerTestCase's dispatch method problematic.
In our app, we use a uri scheme line this: customername.domain.tld.

Can u find a way to change the hardcoding to support more complex routing schemes?

@blanchonvincent
Contributor

@texdc look the last tests methods :) in AbstractHttpControllerTestCaseTest.php : https://github.com/blanchonvincent/zf2/blob/9e523679833669c309aa1a79dd4c1ccff0cf4b7c/tests/ZendTest/Test/PHPUnit/Controller/AbstractHttpControllerTestCaseTest.php :

@trondal changed ! Look an exemple :

public function testAssertUriWithHostname()
{
$this->dispatch('http://my.domain.tld:443');
$routeMatch = $this->getApplication()->getMvcEvent()->getRouteMatch();
$this->assertEquals($routeMatch->getParam('subdomain'), 'my');
$this->assertEquals($this->getRequest()->getUri()->getPort(), 443);
}

@trondal
trondal commented Nov 6, 2012

Fantastic! Good work :-)

@ph77
ph77 commented Nov 8, 2012

Hi Vincent,

I was recently looking for testing controllers in ZF2 as I need it for the project I am currently working on. We need to test routing as well, so dispatching controller objects is not sufficient for us. Your work is great, however I have few questions:

  1. Setting query params from the uri to the request object:
    In the test, If I dispatch to something like '/foo?bar=1' I don't think that $application->getRequest()->getQuery('bar') returns 1. I noticed that while in ZF1 calling $request->setRequestUri() sets GET items, ZF2 http request object doesn't set the query params from the uri.
  2. Suppressing the output:
    Why is attaching your CaptureResponseListener to stop propagating during EVENT_FINISH event better that simply catching the response in the output buffer? What if someone in the application attaches to this event as well and changes the response?
  3. Multiple dispatch per test:
    I didn't try it particularly with your code, but will that work? In my case (with my code, that is slightly different than yours), after the second dispatch I was getting the same output as from the first dispatch. This was not a surprise, but I was wondering if you were thinking about that. By experimenting I made it work by bootstrapping the app again before the next request, but I assume there is a better way how to reset the application between requests. Any ideas?

I am still learning ZF2, so my apology if I am missing something here! Thanks.

@blanchonvincent
Contributor

Hi @ph77,

For your question :
1)

to add parameters :
public function testAssertQueryWithDynamicQueryParams()
{
$this->getRequest()
->setMethod('GET')
->setQuery(new Parameters(array('num_get' => 5)));
$this->dispatch('/tests');
$this->assertQueryCount('div.get', 5);
$this->assertQueryCount('div.post', 0);
}

  1. CaptureResponseListener is for the console mode only. I think it's better that the buffer because you can easily remove the listener :) but i think you are right, i will work on a better solution.

Thanks.

@ph77
ph77 commented Nov 8, 2012
  1. I know how to add query params manually, but my point was that diapatching to '/foo?bar=1' in the browser and in tests will have, in general, different affect. In the controller test shipped with ZF1 this worked differently, so I just thought that the behaviour in ZF2 might be at least surprising if not unexpected.
  2. Sorry, but I don't see how CaptureResponseListener is attached only in console mode...? In the getApplication() in your Zend\Test\PHPUnit\Controller\AbstractControllerTestCase you attach it always or am I mistaken?

Thanks

@blanchonvincent
Contributor

@ph77 I updated the code.

  1. now you can do :

    public function testAssertQueryWithDynamicQueryParamsInDispatch()
    {
    $this->dispatch('/tests?foo=bar&num_get=5');
    $this->assertQueryCount('div.get', 5);
    $this->assertQueryCount('div.post', 0);
    }

  2. Capture is always attached to capture the response. But i will fix that, you are right :)

@blanchonvincent
Contributor

@ph77 i fix the 2) ! I removed the CaptureListener for a better solution : removed the listener SendResponseListener.

Thanks for yours feedbacks !

@ph77
ph77 commented Nov 8, 2012

It was fast :) Looks good!
I had a third comment about multiple dispatch - sorry I edited my post probably meanwhile you were responding. Then I think it would be useful to add assertQueryContentContains() method as it was quite useful in ZF1. Otherwise looks solid, good job!

Thanks

@blanchonvincent
Contributor

@ph77

  1. i had assertQueryContentContains()
  2. i had reset() method to allow multiple dispatch

Thank you :)

@Slamdunk
Contributor
Slamdunk commented Nov 9, 2012

Hi, on late August I've implemented for my company a ControllerTestCase like this, which we are still using today for all our functional and end-to-end testing.
This type of testing is a must-have in such frameworks: yes, now controllers can be tested in isolation (and it's great, we do that), and yes, we still need to rely on Selenium-like tests because of javascript interaction, but this test layer is really useful because gives the ability to do TDD in end-to-end testing, that is not feasable for Selenium-like testing due to its slowness.

So I highly encourage a feature like this.

Some notes on what I've encountered in 2 months of our experience while Application-testing:

  1. For a correct test isolation, before each dispatch, two singleton must be resetted:

    • Zend\EventManager\StaticEventManager::resetInstance();
    • Zend\View\Helper\Placeholder\Registry::unsetRegistry();
  2. If on the same test you want to test multiple sequential dispatches (i.e. for testing a form with CSRF field), you can fearlessly throw away the old Zend\Mvc\Application and create a new one, and thus you need to share the SessionManager component

  3. For this reason, we use the Zend\Session\SessionManager on PHP_SAPI !== cli and a special Our\Session\ArrayManager (https://gist.github.com/4045279) for PHP_SAPI === cli, otherwise you can find very wierd behaviours

  4. Cause we are on a testing environment, it's better to force the application.config.php['module_listener_options']['config_cache_enabled'] to false

  5. We like to have the biggest set of information while testing, so our dispatch method ends with:

    $this->getApplication()->run();
    
    $mvcEvent = $this->getApplication()->getMvcEvent();
    if (($ex = $mvcEvent->getParam('exception')) instanceof \Exception) {
        throw $ex;
    }
  6. We drop and recreate the DB before setting up the application, but maybe this is not the place to implement this feature

@blanchonvincent
Contributor

@Slamdunk thank you for all :) I study all this and do the fix. Thanks

@Slamdunk
Contributor
Slamdunk commented Nov 9, 2012

A deepening about singletons:

  1. Zend\View\Helper\Placeholder\Registry is merely a cache-like system, so unset it with no fear (leaving it alive results in some layout block repeat n-times where n is the number of app-test)
  2. Zend\EventManager\StaticEventManager instead is important for all other unit test that uses application (like https://github.com/doctrine/DoctrineORMModule/blob/master/tests/DoctrineORMModuleTest/Framework/TestCase.php), so you have to back it up on setUp and restore it on tearDown
@blanchonvincent
Contributor

@Slamdunk

  1. I improved the isolation with your recommendation & add the tests.
  2. I have disabled the module cache, thx.
  3. I had a new method assertApplicationException() :

public function testAssertExceptionInAction()
{
$this->dispatch('/exception');
$this->assertResponseStatusCode(500);
$this->assertApplicationException('RuntimeException', 'Foo error');

    $this->dispatch('/exception');
    $this->assertResponseStatusCode(500);
    $this->assertApplicationException('RuntimeException');
}

I study 2) & 3) this week end :)

Thank you so much !

@Slamdunk
Contributor

@blanchonvincent your assertApplicationException is great, but I meant something else.

Let's assume you have a test like this:

$this->dispatch('/');
$this->assertQuery('.login');

Now, suppose something goes wrong, for example a route exception, or a controller exception, or a view helper exception etc. Due to the internal exception handling in zf2 (that is right, because I want to handle them in a hidden way), the only thing you will see while running tests is:

Failed asserting node DENOTED BY .login EXISTS

And this is very annoying, because you may have to change a lot of code to debug the test.

Instead, with a dispatch like this:

$this->getApplication()->run();

$mvcEvent = $this->getApplication()->getMvcEvent();
if (($ex = $mvcEvent->getParam('exception')) instanceof \Exception) {
    throw $ex;
}

PHPUnit will dump the unexpected exception, with message, data and all the stacktrace.
Quick comprehension of what's happend without changing code.


A personal and subjective note on dispatch design: I'd much prefer symfony style of controller url building. We use:

protected function dispatch($method, $uri, array $post = array())
{
    $url = parse_url($uri);
    $query = array();
    if (! empty($url['query'])) {
        parse_str($url['query'], $query);
    }

    $this->request
        ->setMethod($method)
        ->setUri($uri)
        ->setQuery(new Parameters($query))
        ->setPost(new Parameters($post))
    ;

    // [...]
}

So the use cases are:

$this->dispatch('GET', '/home');
$this->disaptch('POST', '/user/edit?id=1', array('name' => 'foo'));

We think that POST use cases are frequent enough to deserve a fast access.
Btw for this point I'll wait your feedback.

@blanchonvincent
Contributor

@Slamdunk

I changed the dispatch method :

public function dispatch($url, $method = HttpRequest::METHOD_GET, $params = array())

I had boolean to trace error :

public function tearDown()
{
if(true === $this->traceError) {
$exception = $this->getApplication()->getMvcEvent()->getParam('exception');
if($exception) {
throw $exception;
}
}
}

Thanks for your comments :)

I will study your other feedback in few time.

@Slamdunk
Contributor

@blanchonvincent the reason why the throw should be directly in dispatch is because of multiple-dispatch tests, so you can be bumped to the exception as soon as it happens. Btw, the throwException issue was already faced in ZF1: http://framework.zend.com/issues/browse/ZF-5721 everyone agreed to throw within the dispatch and parameterize it, but no one did it :)

@blanchonvincent
Contributor

@Slamdunk i think you are right ! i changed and exceptions are throwed in dispatch.

For :

  1. If on the same test you want to test multiple sequential dispatches (i.e. for testing a form with CSRF field), you can fearlessly throw away the old Zend\Mvc\Application and create a new one, and thus you need to share the SessionManager component
  2. For this reason, we use the Zend\Session\SessionManager on PHP_SAPI !== cli and a special Our\Session\ArrayManager (https://gist.github.com/4045279) for PHP_SAPI === cli, otherwise you can find very wierd behaviours

Developer can easily to resolve this problem. I think is not the place to implement this two features.

@Slamdunk
Contributor

@blanchonvincent You are right, the two points are not for this place. Btw, this was an important knowledge in ZF1, so when you branch will be merge, I'll propose a doc for it.

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...est/PHPUnit/Controller/AbstractControllerTestCase.php
+
+ // do not cache module config on testing environment
+ if(isset($applicationConfig['module_listener_options']['config_cache_enabled'])) {
+ $applicationConfig['module_listener_options']['config_cache_enabled'] = false;
+ }
+ $this->applicationConfig = $applicationConfig;
+ return $this;
+ }
+
+ /**
+ * Get the application object
+ * @return Zend\Mvc\ApplicationInterface
+ */
+ public function getApplication()
+ {
+ if(null === $this->application) {
@weierophinney
weierophinney Dec 11, 2012 Member

Invert this, so that the actual work of the method is not done inside a conditional. E.g.

if ($this->application) {
    return $this->application;
}

// initialize application instance, and then return
@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...est/PHPUnit/Controller/AbstractControllerTestCase.php
+ {
+ return $this->getApplication()->getResponse();
+ }
+
+ /**
+ * Set the request URL
+ *
+ * @param string $url
+ */
+ public function url($url, $method = HttpRequest::METHOD_GET, $params = array())
+ {
+ $request = $this->getRequest();
+ if($this->useConsoleRequest) {
+ $params = preg_split('#\s+#', $url);
+ $request->params()->exchangeArray($params);
+ } else {
@weierophinney
weierophinney Dec 11, 2012 Member

Return within the if block, so that the else can be removed, and its body bumped up a level.

Also, add a space between if and the opening paren.

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...est/PHPUnit/Controller/AbstractControllerTestCase.php
+ *
+ * @param string $url
+ */
+ public function url($url, $method = HttpRequest::METHOD_GET, $params = array())
+ {
+ $request = $this->getRequest();
+ if($this->useConsoleRequest) {
+ $params = preg_split('#\s+#', $url);
+ $request->params()->exchangeArray($params);
+ } else {
+ $query = $request->getQuery()->toArray();
+ $post = $request->getPost()->toArray();
+
+ $uri = new HttpUri($url);
+ $queryString = $uri->getQuery();
+ if($queryString) {
@weierophinney
weierophinney Dec 11, 2012 Member

Throughout, add spaces after conditional operators.

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...est/PHPUnit/Controller/AbstractControllerTestCase.php
+ $request = $this->getRequest();
+ if($this->useConsoleRequest) {
+ $params = preg_split('#\s+#', $url);
+ $request->params()->exchangeArray($params);
+ } else {
+ $query = $request->getQuery()->toArray();
+ $post = $request->getPost()->toArray();
+
+ $uri = new HttpUri($url);
+ $queryString = $uri->getQuery();
+ if($queryString) {
+ parse_str($queryString, $query);
+ }
+ if($method == HttpRequest::METHOD_POST) {
+ $post = $params;
+ } else if($method == HttpRequest::METHOD_GET) {
@weierophinney
weierophinney Dec 11, 2012 Member

but use elseif instead of else if.

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...PHPUnit/Controller/AbstractHttpControllerTestCase.php
+ */
+ protected function getResponseHeader($header)
+ {
+ $response = $this->getResponse();
+ $headers = $response->getHeaders();
+ $responseHeader = $headers->get($header, false);
+ return $responseHeader;
+ }
+
+ /**
+ * Assert response header exists
+ *
+ * @param string $header
+ * @return void
+ */
+ public function assertHeader($header)
@weierophinney
weierophinney Dec 11, 2012 Member

This is ambigous -- are you asserting against a response header or a request header? I'd rename this to assertResponseHeader, and, actually, more accurately to assertHasResponseHeader.

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...PHPUnit/Controller/AbstractHttpControllerTestCase.php
+ $responseHeader = $this->getResponseHeader($header);
+ if(false === $responseHeader) {
+ throw new PHPUnit_Framework_ExpectationFailedException(sprintf(
+ 'Failed asserting response header "%s" found', $header
+ ));
+ }
+ $this->assertNotEquals(false, $responseHeader);
+ }
+
+ /**
+ * Assert response header does not exist
+ *
+ * @param string $header
+ * @return void
+ */
+ public function assertNotHeader($header)
@weierophinney
weierophinney Dec 11, 2012 Member

Same comment as last -- rename to assertNotHasResponseHeader

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...PHPUnit/Controller/AbstractHttpControllerTestCase.php
+ if(false !== $responseHeader) {
+ throw new PHPUnit_Framework_ExpectationFailedException(sprintf(
+ 'Failed asserting response header "%s" WAS NOT found', $header
+ ));
+ }
+ $this->assertEquals(false, $responseHeader);
+ }
+
+ /**
+ * Assert response header exists and contains the given string
+ *
+ * @param string $header
+ * @param string $match
+ * @return void
+ */
+ public function assertHeaderContains($header, $match)
@weierophinney
weierophinney Dec 11, 2012 Member

Rename to assertResponseHeaderContains

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...PHPUnit/Controller/AbstractHttpControllerTestCase.php
+ throw new PHPUnit_Framework_ExpectationFailedException(sprintf(
+ 'Failed asserting response header "%s" exists and contains "%s", actual content is "%s"',
+ $header, $match, $responseHeader->getFieldValue()
+ ));
+ }
+ $this->assertEquals($match, $responseHeader->getFieldValue());
+ }
+
+ /**
+ * Assert response header exists and contains the given string
+ *
+ * @param string $header
+ * @param string $match
+ * @return void
+ */
+ public function assertNotHeaderContains($header, $match)
@weierophinney
weierophinney Dec 11, 2012 Member

Rename to assertNotResponseHeaderContains

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...PHPUnit/Controller/AbstractHttpControllerTestCase.php
+ throw new PHPUnit_Framework_ExpectationFailedException(sprintf(
+ 'Failed asserting response header "%s" DOES NOT CONTAIN "%s"',
+ $header, $match
+ ));
+ }
+ $this->assertNotEquals($match, $responseHeader->getFieldValue());
+ }
+
+ /**
+ * Assert response header exists and matches the given pattern
+ *
+ * @param string $header
+ * @param string $pattern
+ * @return void
+ */
+ public function assertHeaderRegex($header, $pattern)
@weierophinney
weierophinney Dec 11, 2012 Member

Rename to assertResponseHeaderRegex

@weierophinney weierophinney commented on an outdated diff Dec 11, 2012
...PHPUnit/Controller/AbstractHttpControllerTestCase.php
+ throw new PHPUnit_Framework_ExpectationFailedException(sprintf(
+ 'Failed asserting response header "%s" exists and matches regex "%s", actual content is "%s"',
+ $header, $pattern, $responseHeader->getFieldValue()
+ ));
+ }
+ $this->assertEquals(true, (boolean)preg_match($pattern, $responseHeader->getFieldValue()));
+ }
+
+ /**
+ * Assert response header does not exist and/or does not match the given regex
+ *
+ * @param string $header
+ * @param string $pattern
+ * @return void
+ */
+ public function assertNotHeaderRegex($header, $pattern)
@weierophinney
weierophinney Dec 11, 2012 Member

Rename to assertNotResponseHeaderRegex

@weierophinney weierophinney commented on the diff Dec 11, 2012
library/Zend/Test/PHPUnit/Mvc/Service/RouterFactory.php
+use Zend\Mvc\Router\Http\TreeRouteStack as HttpRouter;
+use Zend\ServiceManager\FactoryInterface;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * @category Zend
+ * @package Zend_Test
+ * @subpackage PHPUnit
+ */
+class RouterFactory implements FactoryInterface
+{
+ public function createService(ServiceLocatorInterface $serviceLocator, $cName = null, $rName = null)
+ {
+ $config = $serviceLocator->get('Config');
+ $routerConfig = isset($config['router']) ? $config['router'] : array();
+ return HttpRouter::factory($routerConfig);
@weierophinney
weierophinney Dec 11, 2012 Member

Won't this restrict us to testing HTTP endpoints (vs Console)? Why not simply re-use the Zend\Mvc\Service\* factories? What's the rationale?

@weierophinney weierophinney commented on the diff Dec 11, 2012
...d/Test/PHPUnit/Mvc/Service/ServiceListenerFactory.php
+ * @subpackage PHPUnit
+ */
+class ServiceListenerFactory extends BaseServiceListenerFactory
+{
+ public function __construct()
+ {
+ // merge basee config with specific tests config
+ $this->defaultServiceConfig = array_replace_recursive(
+ $this->defaultServiceConfig,
+ array(
+ 'factories' => array(
+ 'Request' => function($sm) {
+ return new \Zend\Http\PhpEnvironment\Request();
+ },
+ 'Response' => function($sm) {
+ return new \Zend\Http\PhpEnvironment\Response();
@weierophinney
weierophinney Dec 11, 2012 Member

Same comment here -- this appears to lock the testing API to HTTP only, yet it's clear that you also intend to test Console endpoints. Can you explain?

@blanchonvincent
blanchonvincent Dec 11, 2012 Contributor

This is only to test like a HTTP client. Without that, the framework use always console because we are in CLI.

In AbstractControllerTestCase, there is :

// we use our own override only if we want http simulation
     if(!$this->useConsoleRequest) {
            $consoleServiceConfig = array(
                'service_manager' => array(
                    'factories' => array(
                        'ServiceListener' => 'Zend\Test\PHPUnit\Mvc\Service\ServiceListenerFactory',
                    ),
                ),
            );
            $appConfig = array_replace_recursive($appConfig, $consoleServiceConfig);
        }
        $this->application = Application::init($appConfig);

Flag $useConsoleRequest provide possibility to switch in console or HTTP mode.

@weierophinney
weierophinney Dec 13, 2012 Member

Ah, right -- forgot about that! :-)

@blanchonvincent
Contributor

@weierophinney i changed the name methods like you want, fix CS (space after if) & fix all your comments.

@weierophinney weierophinney added a commit that referenced this pull request Dec 13, 2012
@weierophinney weierophinney [#2794] fix assertion
- Use assertNotSame(false, /* statement */) instead of
  assertNotEquals(), as stripos will return 0 as a position (which is a
  successful match)
3784e88
@weierophinney weierophinney added a commit that referenced this pull request Dec 13, 2012
@weierophinney weierophinney [#2794] CS review
- Fixed various CS issues as caught by php-cs-fixer, as well as manually reading
  code (removed "@return void", added whitespace after casting operators,
  removed whitespace between opening "<?php" and file annotation, etc.)
- Made assertions more semantically correct (used assertFalse() and assertTrue()
  when possible; used assertSame in some situations where needed)
90abb18
@ninja-saigon ninja-saigon referenced this pull request in blanchonvincent/au-coeur-de-zend-framework-2 Jan 18, 2015
Open

PHPUnit test does not work on zf2 version 2.3.3 #2

@weierophinney weierophinney added a commit to zendframework/zend-test that referenced this pull request May 15, 2015
@weierophinney weierophinney [zendframework/zendframework#2794] fix assertion
- Use assertNotSame(false, /* statement */) instead of
  assertNotEquals(), as stripos will return 0 as a position (which is a
  successful match)
af868aa
@weierophinney weierophinney added a commit to zendframework/zend-test that referenced this pull request May 15, 2015
@weierophinney weierophinney [zendframework/zendframework#2794] CS review
- Fixed various CS issues as caught by php-cs-fixer, as well as manually reading
  code (removed "@return void", added whitespace after casting operators,
  removed whitespace between opening "<?php" and file annotation, etc.)
- Made assertions more semantically correct (used assertFalse() and assertTrue()
  when possible; used assertSame in some situations where needed)
39503da
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment