symfony2 phpunit session doesn't start - unit-testing

I have a strange problem with $_SESSION in my application
For different reasons that i don't explain here i had the necessity to set in the session the environment in my AppKernel.php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
protected $session;
public function initializeContainer()
{
parent::initializeContainer();
$this->session = $this->container->get('session');
$this->session->set('isTestEnv', $this->getEnvironment() == 'test');
}
In another class that i use to manage the request to some API i need now to get that param
namespace Bioversity\ServerConnectionBundle\Repository;
use Symfony\Component\HttpFoundation\Session\Session;
use Bioversity\ServerConnectionBundle\Repository\ServerResponseManager;
use Bioversity\ServerConnectionBundle\Repository\ServerResponseRequestQueryManager;
class ServerRequestManager
{
protected $wrapper= "http://url/to/the/api.php";
public function __construct()
{
if($_SESSION['_sf2_attributes']['isTestEnv'] == 'test')
{
$this->wrapper= "http://url/to/the/api.test.php";
}
}
Everything works fine in the browser, but when i try to run the test i get a strange error
48) ServerConnectionBundle\Tests\Repository\TraitConnectionRepositoryTest::testGetTags
ErrorException: Notice: Undefined variable: _SESSION in ServerConnectionBundle/Repository/ServerRequestManager.php line 41
---------------EDIT------------
I had updated my code,
now i have a services like this
parameters:
env: %kernel.environment%
services:
bioversity_server_connection:
class: Bioversity\ServerConnectionBundle\Repository\ServerRequestManager
arguments: [%env%]
and in my class i added
class ServerRequestManager
{
public function __construct($env)
{
print_r($env);
//if(array_key_exists('isTestEnv', $_SESSION['_sf2_attributes']))
//{
//if($_SESSION['_sf2_attributes']['isTestEnv'] == 'test'){
if($env == 'test')
{
$this->wrapper= "http://temp.wrapper.grinfo.net/TIP/Wrapper.test.php";
$this->setDatabaseOntology('TEST-'.$this->getDatabaseOntology());
$this->setDatabasePGRSecure('TEST-'.$this->getDatabasePGRSecure());
$this->setDatabaseUsers('TEST-'.$this->getDatabaseUsers());
}
//}
}
I had imported the services.yml in my config.yml
but I only have this error
Warning: Missing argument 1 for Bioversity\ServerConnectionBundle\Repository\ServerRequestManager::__construct(), called in /home/aczepod/Sites/Bioversity/src/Bioversity/SecurityBundle/Repository/ServerConnection.php
What is wrong now!?

Woha, what the heck are you doing. Symfony has the parameter kernel.environment which refers to the current environment! So simple inject %kernel.environment% as argument into your service.
Btw. with PHP-CLI (running tests) there is no $_SESSION at all.

Related

Compiler pass - resolve target entity doesn't load

I'm working on a bundle and i need to load a doctrine resolve_target_entities from a configuration parameter.
This article should be my solution, the fact is that using the bundle it seems not to load the "compiler pass class".
This is my bundle class
class PersonalBundle extends Bundle
{
public function build(ContainerBuilder $container){
parent::build($container);
$container->addCompilerPass(new ResolveTargetEntitiesPass());
}
}
This is the ResolveTargetEntitiesPass class
class ResolveTargetEntitiesPass implements CompilerPassInterface
{
/**
* {#inheritdoc}
*/
public function process(ContainerBuilder $container)
{
// Gets the custom entity defined by the user (or the default one)
$customEntityClass = $container->getParameter('personal.custom_class');
// Skip the resolve_target_entities part if user has not defined a different entity
if (DefaultClassInterface::DEFAULT_ENTITY_CLASS == $customEntityClass) {
return;
}
// Throws exception if the class isn't found
if (!class_exists($customEntityClass)) {
throw new ClassNotFoundException(sprintf("Can't find class %s ", $customEntityClass));
}
// Get the doctrine ResolveTargetEntityListener
$def = $container->findDefinition('doctrine.orm.listeners.resolve_target_entity');
// Adds the resolve_target_enitity parameter
$def->addMethodCall('addResolveTargetEntity', array(
DefaultClassInterface::DEFAULT_ENTITY_CLASS, $customEntityClass, array()
));
// This was added due this problem
// https://stackoverflow.com/a/46656413/7070573
if (version_compare(Version::VERSION, '2.5.0-DEV') < 0 && !$def->hasTag('doctrine.event_listener')) {
$def->addTag('doctrine.event_listener', array('event' => 'loadClassMetadata'));
} elseif (!$def->hasTag('doctrine.event_subscriber')) {
$def->addTag('doctrine.event_subscriber');
}
}
}
When i use the class it raises this error
Expected value of type "PersonalBundle\Entity\DefaultClass"
for association field "PersonalBundle\Entity\Group#$defaultClass", got
"App\Entity\CustomClass" instead.
As i said it seems not to load the ResolveTargetEntitiesPass...
Thanks
So i solved the problem changing the priority of the compiler pass.
I've tried to move the bundle on top in config/bundle.php and it started working, then following this https://symfony.com/blog/new-in-symfony-3-2-compiler-passes-improvements i've left the default type but increased the priority (from 0, default, to 1).
I'm not sure which service has been "downgraded" so if anyone has an idea it's welcome.
<?php
// ...
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
class PersonalBundle extends Bundle
{
public function build(ContainerBuilder $container){
parent::build($container);
$container->addCompilerPass(new ResolveTargetEntitiesPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 1);
}
}

How inject a parameter/service into a Doctrine Entity Listener

I am using Symfony 4 try to inject a parameter into an Doctrine Entity Listener
Konfiguration:
App\EventListener\MyListener:
arguments:
- "%kernel.cache_dir%"
tags:
- { name: doctrine.orm.entity_listener }
Annotation of Entity Class:
#ORM\EntityListeners({"App\EventListener\MyListener"})
Listener:
namespace App\Eventlistener;
use Doctrine\ORM\Event\LifecycleEventArgs;
class MyListener {
private $cacheDirectory;
public function __construct($cacheDirectory)
{
$this->cacheDirectory = $cacheDirectory;
}
public function postUpdate($entity, LifecycleEventArgs $args)
{
...
}
}
When updating the Entity i get the Exception:
Too few arguments to function __construnt().
0 passed in ...\vendor\doctrine\doctrine-bundle\Mapping\ContainerAwareEntityListenerResolver.php on line 76 and exactly 1 expected
I also tried setter injection, but the setter method seems never to be called.
(This is a simplified Demo - I actually will need to inject a service and use it in postUpdate)
Documentation: https://symfony.com/doc/master/bundles/DoctrineBundle/entity-listeners.html (but without DI)
UPDATE: I found this Answer but this is not working with symfony 4.

MVC Core 2.0 Unit Testing and Automapper

I am attempting to Unit Test a method that uses Automapper ProjectTo and I'm not sure how to register the mappings in MVC Core. I am using the built in unit testing.
The following is my unit test.
[TestClass]
public class BusinessGenderServiceTest
{
[ClassInitialize]
public static void Init(TestContext context)
{
}
[TestMethod]
public void GetTest()
{
var options = new DbContextOptionsBuilder<GotNextDbContext>()
.UseInMemoryDatabase(databaseName: "GetTest")
.Options;
using (var context = new GotNextDbContext(options))
{
context.GenderLanguage.Add(new GenderLanguage { Id = 1, Name = "Male", Language = 1 });
context.GenderLanguage.Add(new GenderLanguage { Id = 2, Name = "Female", Language = 1 });
context.GenderLanguage.Add(new GenderLanguage { Id = 3, Name = "Hombre", Language = 2 });
context.GenderLanguage.Add(new GenderLanguage { Id = 4, Name = "Hombre", Language = 2 });
context.SaveChanges();
}
using (var context = new GotNextDbContext(options))
{
var service = new GenderService(context);
var result = service.Get(1);
Assert.AreEqual(2, result.Count());
}
}
}
I am getting the following error when I run the test:
Message: Test method GotNext.Test.BusinessGenderServiceTest.GetTest threw exception:
System.InvalidOperationException: Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.
I was able to solve this problem by configuring and initializing automapper in the Init method of each test class.
For example
[ClassInitialize]
public static void Init(TestContext testContext)
{
var mappings = new MapperConfigurationExpression();
mappings.AddProfile<LocationProfile>();
mappings.AddProfile<CompanyProfile>();
Mapper.Initialize(mappings);
}
You can configure AutoMapper in class like this:
public static class AutoMapperConfig
{
public static IMapper Initialize()
{
return new MapperConfiguration((cfg =>
{
cfg.CreateMap<User, UserDto>();
})).CreateMapper();
}
}
And next use it in startup.cs ConfigureService method
services.AddSingleton(AutoMapperConfig.Initialize());
Create a class or classes that configure AutoMapper and instantiate (and call methods, if applicable) in the Startup class.
I got this same error ("System.InvalidOperationException: Mapper not initialized. Call Initialize with appropriate configuration. ...") when I inadvertently / mindlessly switched between AutoMapper's Instance API (which I did have configured) and AutoMapper's Static API (which I did NOT have configured).
Looking closely at the line of code flagged in the error message, I realized I used upper-case 'M' Mapper.Map() instead of my instance member lower-case 'm' mapper.Map().

PHPUnit Mock overrides existing methods

I'm writing a unit test for a REST Service connector which is using a third party tool called Httpful.
Because I do not want to send real requests to the server, I mocked the "send" method from Httpful\Request:
$mockedRequest = $this->getMock('Httpful\Request', array('send'), array(), '', false);
$mockedRequest->expects($this->once())->method('send');
This works fine, but the Request Class has a method called expects itself, which I use in my actual code to define the acceptable mime type of the response.
$this
->getRequest('GET')
->uri(ENDPOINT . $configurationId) //by default this returns a Request Object (now mocked request)
->expects('application/json') //crashes ...
->send();
When the code gets executed, I get the following error (which is understandable):
Argument 1 passed to Mock_Request_938fb981::expects() must implement interface PHPUnit_Framework_MockObject_Matcher_Invocation, string given
Is there something like a configurable prefix for methods coming from the Mock Class like "expects"?
I don't think that you will be able to do that using the PHPUnit_MockObject class. But you can code your own and use that instead.
class MockRequest extends \Httpful\Request {
public $isSendCalled = false;
public $isUriCalled = false;
public $isExpectsCalled = false;
public function uri($url) {
if($url !== '<expected uri>') {
throw new PHPUnit_Framework_AssertionFailedError($url . " is not correct");
}
$this->isUriCalled = true;
return $this;
}
public function expects($type) {
if($type !== 'application/json') {
throw new PHPUnit_Framework_AssertionFailedError($type . " is not correct");
}
$this->isExpectsCalled = true;
return $this;
}
public function send() {
$this->isSendCalled = true;
}
}
Your line for creating the mock then just becomes:
$mockedRequest = new MockRequest();
If the constructor fo
Then in your test you can verify that the methods are called with
$this->assertTrue($mockedRequest->isSendCalled);
$this->assertTrue($mockedRequest->isUriCalled);
$this->assertTrue($mockedRequest->isExpectsCalled);
This isn't a very dynamic mock but it will pass the type hinting and does your check for you. I would create this mock in the same file as your test (though be careful about not accidentally redefining this class elsewhere in your test suite). But it gets you around the problem of having expects being overridden.
The PHPUnit_Framework_MockObject_MockObject is an interface that sets the signature for expects() also which your class wouldn't meet and so there would be an error if you were able to rename the method.
https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/src/Framework/MockObject/MockObject.php

Error when using Code First in web service "System.Data.ProviderIncompatibleException: The provider did not return a ProviderManifestToken string."

I'm using Code First. Everything works just fine (inserts, updates, selects) everything is tested. The problem comes when I try to use the web services. I get the error "System.Data.ProviderIncompatibleException: The provider did not return a ProviderManifestToken string.". Looking at the inner exception I get this message "Could not determine storage version; a valid storage connection or a version hint is required.".
The web service Code:
/// <summary>
/// Summary description for UserServices
/// </summary>
[WebService(Namespace = "http://localhost:3955/WebServices/UserServices")]
//[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
//[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class UserServices : System.Web.Services.WebService
{
[WebMethod]
public bool LoginControlPanelUser(string user, string password)
{
if(Membership.ValidateUser(user, password))
{
return DbUsersDAO.HasAuthenticationType(user, password);
}
return false;
}
}
The DAO code:
public static bool HasAuthenticationType(string user, string authenticationTypeCode)
{
try
{
using (VirtusCloudCoreContext ctx = new VirtusCloudCoreContext())
{
DBUser User = ctx.DBUsers.SingleOrDefault(u => u.Login.Equals(user) && u.Active.Equals(true));
if (User != null)
{
return DBAuthenticationTypesDAO.GetById(User.DBAuthenticationTypeId).Name.Equals("Admin");
}
}
return false;
}
catch (Exception ex)
{
ErrorsHelper.InsertError(ex);
throw ex;
}
}
The Context class:
public VirtusCloudCoreContext()
{
Database.SetInitializer<VirtusCloudCoreContext>(new VirtusCloudCoreContextInitializer());
this.Database.Connection.ConnectionString = "Data Source=localhost\SQLEXPRESS;Database=DatabaseName;User Id=******;Password=*******;" ;
}
I get the exception when I try to get the user.... Any ideas?
This error occurs often when the connection string is wrong but I think in your case it's because you're trying to manually set the connection string.
Try making your context inherit from DbContext and take a connection string in your constructor which it passes through to the base constructor, like this:
public class VirtualCloudCoreContext : DbContext {
public VirtualCloudCoreContext(string connectionString)
: base (connectionString) {
}
}
I'm using a new DB-generated EDMX in VS2012 Web Project with a separate class file - both projects have EF 6.1.1 installed. Even though I'm using SQL 2012, I had to edit the EDMX file directly and change it to ProviderManifestToken="2008" from 2012.
Not sure if related to Telerik Grid/EntityDataSource or not. More mention of this issue here but related to VS2013.