We are currently using CodeCeption to do some acceptance testing, but I would like to also add unit testing to the current setup.
Has anyone done Unit testing in Zend Framework 2 project using CodeCeption? And if so, how did you set up the environment?
Found this in codeception docs: http://codeception.com/docs/modules/ZF2
There is an example in this github project: https://github.com/Danielss89/zf2-codeception
I solved this problem by using PHPUnit. I followed the Zend PHPUnit guide, http://framework.zend.com/manual/current/en/tutorials/unittesting.html, which only got me so far. But, I was able to bootstrap Zend using a phpunit.xml file and pointing that to _bootstrap.php. Codeception is also able to bootstrap my tests using the _bootstrap.php file. So, now I can run my tests using both:
phpunit --bootstrap tests/unit/_bootstrap.php
and
php vendor/bin/codecept run unit
I was surprised to see how few examples there are for this. I was writing tests for a job queue client. Here is a bit of my test:
protected function setUp()
{
$this->serviceManager = new ServiceManager(new ServiceManagerConfig());
$config = Bootstrap::getConfig();
$this->serviceManager->setService('ApplicationConfig', $config);
$this->serviceManager->get('ModuleManager')->loadModules();
$this->client = $this->serviceManager->get('jobclient');
$this->client->addServers(array(array('ip' => '127.0.0.1', 'port' => '666')));
}
public function testServiceCreateSuccess() {
$this->client->setQueue($this->testData['queue']);
$this->assertEquals($this->client->getQueue(), $this->testData['queue'], 'We get the expected queue');
}
I mocked the job client and had a local config. My _bootstrap.php file looks basically the same as the Zend example except that I am using factories defined in the service config to manage some objects. So, I performed the "setService" method in the test setup rather then in the bootsrap init.
Related
I am using aspnetboilerplate 5.1.0.
In the ProjectName.Web.Tests I have run into a situation that I cannot solve.
I have set up web tests for my controller using [Fact] or [Theory].
When I attempt to run the tests using GetResponseAsString(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) found in the webtestbase class. All the tests fail.
Here is an example of my Test:
[Fact]
public async Task Index_Test()
{
//Act
var response = await GetResponseAsStringAsync(
GetUrl<HomeController>(nameof(HomeController.Index))
);
//Assert
response.ShouldNotBeNullOrEmpty();
}
The Tests all fail on this:
Message:
Shouldly.ShouldAssertException : response.StatusCode
should be
HttpStatusCode.OK
but was
HttpStatusCode.NotFound
I have other aspnetboilerplate projects in version 3.8.3 and 4.2.1 and the web tests work just fine. So I'm not sure why the server is not able to find the action methods on my controllers.
The service tests found in the ProjectName.Tests project run just fine.
I found the culprit. The problem I was experiencing was due to attempting to copy a project for web unit tests from one of the aspnetboilerplate project template repositories and updating all of the references and class names to match the names and namespaces in the destination VS solution.
I submitted a similar question on the aspnetboilerplate github account.
https://github.com/aspnetboilerplate/aspnetboilerplate/issues/5463.
Ultimately, here is what happened.
After going through the same process with a newer project. I found that In the
class file that would by default be named AbpProjectNameWebTestBase.cs in the method
protected override IWebHostBuilder CreateWebHostBuilder()
{
return base
.CreateWebHostBuilder()
.UseContentRoot(ContentRootFolder.Value)
.UseSetting(WebHostDefaults.ApplicationKey, typeof(AbpProjectNameWebModule).Assembly.FullName);
}
I mistakenly replaced AbpProjectNameWebModule with AbpProjectNameTestModule instead of AbpProjectNameWebMvcModule. This was trying to use the Application Service Unit test project as the web project. Therefore it could not find any of the referenced URI's and therefore returned httpStatusCode.NotFound.
After fixing this reference. I started getting exceptions that pertained to the public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) method.
These were things like adding app.UseAuthentication() and app.UseAuthorization() as well as needing to add a Middleware to provide a ClaimsIdentity and ClaimsPrincipal for the context.User (i.e. app.UserMiddleware<TestAuthenticationMiddleware>())
Now, I am able to get my web unit tests to run as I had in previous versions.
I got DataFixtures set up, that I can load via console into my test database.
$ php bin/console doctrine:fixtures:load --env=test -n
> purging database
> loading App\DataFixtures\PropertyFixtures
> loading App\DataFixtures\UserFixtures
> loading App\DataFixtures\UserPropertyFixtures
works like a chram
But I am lost how to load these fixtures automatically with my service unit tests, without having to run the command manually before testing. There has to be another way!
What I found so far is descriptions for testing with older versions of symfony or for testing Controllers. Who wants to test Controllers anyway, if you can avoid it?
The Liip\FunctionalTestBundle also seems to work only for WebTestCases at least I have seen no way to extend or replace the usual KernelTestCase.
So is there any way I can maybe run the command with the setUp() method of my test class?
Any link to a tutorial for symfony 4? Any example for a service? I cannot imagine, that I am the only person with that problem.
I got a solution and although it is not full of beauty and style here it is. More elegant alternatives are appreciated.
I extended my Kernel class found in Kernel.php with a class called AppKernel.
To activate it for tests and only those I changed my phpunit.xml file:
<php>
<ini name="error_reporting" value="-1" />
<env name="KERNEL_CLASS" value="App\AppKernel" />
So now only for tests this class is loaded.
In the AppKernel Class I extended the boot method as follows:
public function boot()
{
parent::boot();
$this->importDataFixtures();
}
/**
* Loads the tests data for DataFixtures when we start phpUnit.
*/
protected function importDataFixtures()
{
system('php /var/www/octopus/bin/console doctrine:fixtures:load --env=test -n');
}
So of course the call of the import via system is ugly, but it works. If somebody has a better idea, please let my know.
I'm trying to upgrade my Grails 2 project to Grails 3. I'm having problems with running tests for code blocks that use logging as it throws NoSuchPropertyException for log property. This was no problem with Grails 2 as the property is automatically injected. How do I get this working in Grails 3? I'm using 3.0.2.
Add the #groovy.util.logging.Slf4j class annotation to your Spec and log will be injected.
I've been doing this in my Groovy classes, I don't know whether this will work for your tests:
import org.slf4j.Logger
import org.slf4j.LoggerFactory
// within my class that I want to call log on
private static final Logger log = LoggerFactory.getLogger(MyClass.class)
// now you can call log from within a method
log.info("Log foo")
I have an issue where the global constraints setup in the Config are not working when running unit tests.
This is in my Config.groovy:
grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
in my test I have tried this:
static doWithConfig(c){
c.grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
and also in the setupSpec():
grailsApplication.config.grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
All I'm doing in my test is trying to create a domain object from a json string. Is there anything special that I should be doing to get this to work in the Unit test? This is also using the Gorm-MongoDb plugin.
What is the way to test my packages in workbench. If I write a unit test then no classes are autoloaded. So this means that:
<?php
use \Mockery as m;
class ExampleTest extends TestCase {
public function tearDown()
{
m::close();
}
/**
* A basic functional test example.
*
* #return void
*/
public function testShouldReturnValidServer()
{
$mock = m::mock('MailChimp[sendCurl]');
MailChimp::listSubscribe( array( 'id' => 'c79a023ff2', 'email_address' => 'dennieriechelman#gmail.com'));
}
}
results in a error saying that class TestCase is not found. When I add class TestCase to the autoload in my composer.json (the one in my package folder) the class is available. However then I get the next error that "Illuminate\Foundation\Testing\TestCase" is not available etc. etc.
So my question is what should I autoload in my composer.json in my package folder? Everything just like in my main composer.json or is there some other way that I am missing.
I know that in the manuel it says"
You may git init from the workbench/[vendor]/[package] directory and git push your package straight from the workbench! This will allow you to conveniently develop the package in an application context without being bogged down by constant composer update commands.
However I do not understand this. Can someone explain what is meant with this? By the way I am familiar with git. I just do not get the context.
EDIT1
As far I understand now is that you push your package to your repository and then include it in your main composer.json as package. I just do not see how this is helpful when developing. Hopefully I understand this wrong.. :)
EDIT2
I was wrong. You keep your package in workbench until it stable. Just like Nils pointed out below.The question still remains though. How do I create an environment in which I can unit test with the app started. I mean like testing a model where I can mock the facades etc. Or is doing this in the workbench bad practice?
I created a package for this purpose at https://github.com/orchestral/testbench
If you don't mind merging the results of your workbench testing with the results of your main application, you can simply add extra directories to your main phpunit.xml in your laravel root like this:
<testsuites>
<testsuite name="Application Test Suite">
<directory>./app/tests/phpunit/</directory>
<directory>./workbench/vendor/packageOne/tests/</directory>
<directory>./workbench/vendor/packageTwo/tests/</directory>
</testsuite>
</testsuites>
Then in the tests folder of your package, place your phpunit tests as normal, along with the TestCase.php file, adjusting the createApplication() function to be:
<?php
class TestCase extends \Illuminate\Foundation\Testing\TestCase {
public function createApplication()
{
$unitTesting = true;
$testEnvironment = 'testing';
return require './bootstrap/start.php';
}
Make sure your package composer.json auto-loads that TestCase.php file like so:
"autoload": {
"classmap": [
"tests/phpunit/TestCase.php"
]
}
Run composer dump-autoload -o to get everything aligned and then you should be able to run phpunit from your laravel root and it will test both your application and your packages.
Extend from the proper namespace and you should be able to run tests from package dir.
class ExampleTest extends \Illuminate\Foundation\Testing\TestCase {
..
}
See also Laravels neat testing helpers in workbench?