Random String passed as the same string php - php

Trying to create a functional test using PHP with Behat and I want a random string for an email, but I want the string to be random every time a new test runs, but I want to pass the same string created to different tests as a parameter.
So if I generate a 10 digit string, I would like to generate the string and then pass it though other tests as the same 10 digit sequence
I'm new to PHP so I'm not exactly positive how to set it up, but here's what I have so far in my Behat context file
class FeatureContext implements Context {
private $MailPage;
private $registrationpage;
/**
* Initializes context.
*
* Every scenario gets its own context instance.
* You can also pass arbitrary arguments to the
* context constructor through behat.yml.
*/
public function __construct(MailPage $mailPage, RegistrationPage $registrationpage)
{
// Page obects injected directly in constructor with type hints.
$this->MailPage = $MailPage;
$this->registrationpage = $registrationpage;
}
/**
* #BeforeSuite
*/
public static function generateRandomString() {
// Generate random string for Email implementation.
$randomString = bin2hex(openssl_random_pseudo_bytes(10));
return $randomString;
}
/**
* #Given /^I register a temporary email address $/
*/
public function iRegisterATemporaryEmailAddress()
{
$this->MailPage->grabNewEmail(self::generateRandomEmail());
}
/**
* #Given /^I register a Developer account$/
*/
public function iRegisterADeveloperAccount()
{
$this->registrationpage->fillInFormDetails(self::generateRandomEmail());
}
The Problem I run into is that with the parameter as it is, It generates a different string every time it's called, but I only want it to generate it once for the entire suite. Any ideas?

1- Call your method from the constructor.
2- Save the generated value in a variable using this
private $randomString ;
public function __construct(MailPage $mailPage, RegistrationPage $registrationpage)
{
//your code
$this->randomString = $this->generateRandomString();
}
3- To use this variable you can call it inside your class methods like this $this->randomString.
Classes which have a constructor method call this method on each
newly-created object, so it is suitable for any initialization that
the object may need before it is used.

Related

Test for getters in PHP

class myclass {
private $myemail = '';
private $myPrefix = '';
/**
* #return string
*/
public function getmyPrefix()
{
return $this->myPrefix;
}
/**
* #return string
*/
public function getmyEmail()
{
return $this->myemail;
}
/**
* #param string $email
*/
public function setmyEmail($email)
{
$this->myemail = $email;
}
}
I want to write a php unit tests to test the private variables in this class but I am not sure how to test the variable $myPrefix because it does not have a setter ? Do I need to create a mock class ?
Thanks
You can do a simple test to ensure the initial value is null by simply testing the return from the class. Then use your Setter or __construct() to populate the field, and test the return from the getter again.
Optionally, and you do not need to go to this level of testing internal private fields as they should not change from outside the module, you can use Reflection.
I have some library classes that do things based on inputs, and I do use reflection to test the odd setting to be updated/set as I would expect for the function/method to work properly. This is done sparingly as the private values should not be changed external to the code library, but the test is for developer documentation purposes, and to ensure the basic functionality and assumptions in the code are not broken.
From the PHP Manual
$class = new ReflectionClass('myClass');
$property = $class->getProperty('myPrefix');
$this->assertEquals("Something from your setter", $property);
I would only use this to ensure that the set method (or constructor) is directly setting the field, not manipulating it in any way. However, with a get method, this is not needed since the get..() can test this. I only added the quick reference code to show you could test a value that did not have a get method.

doctrine2 extra lazy fetching of association

I have a Thread entity which has a OneToMany association with a Message entity. I am fetching a thread with a DQL query, and I want to limit its amount of messages to 10. Therefore I am setting the fetch mode to EXTRA_LAZY as below.
class Thread
{
// ...
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="Profile\Entity\Message", mappedBy="thread", fetch="EXTRA_LAZY")
* #ORM\OrderBy({"timeSent" = "ASC"})
*/
protected $messages;
}
This allows me to use the slice method to issue a LIMIT SQL query to the database. All good so far. Because my messages are encrypted, I need to decrypt them in my service layer before handling the thread object off to the controller (and ultimately view). To accomplish this, I am doing the following in my service:
foreach ($thread->getMessages()->slice(0, 10) as $message) {
// Decrypt message
}
The call to slice triggers an SQL query that fetches 10 messages. In my view, I am doing the following to render the thread's messages:
$this->partialLoop()->setObjectKey('message');
echo $this->partialLoop('partial/thread/message.phtml', $thread->getMessages());
The problem is that this fetches the entire collection of messages from the database. If I call slice as in my service, the same SQL query with LIMIT 10 is issued to the database, which is not desirable.
How can I process a limited collection of messages in my service layer without issuing another SQL query in my view? That is, to have doctrine create a single SQL query, not two. I could simply decrypt my messages in my view, but that kind of defeats the purpose of having a service layer in this case. I could surely fetch the messages "manually" and add them to the thread object, but if I could do it automatically through the association, then that would be much preferred.
Thanks in advance!
How about a slightly different approach than most have suggested:
Slice
In the Thread entity, have a dedicated method for returning slices of messages:
class Thread
{
// ...
/**
* #param int $offset
* #param int|null $length
* #return array
*/
public function getSliceOfMessages($offset, $length = null)
{
return $this->messages->slice($offset, $length);
}
}
This would take care of easily retrieving a slice in the view, without the risk of fetching the entire collection.
Decrypting message content
Next you need the decrypted content of the messages.
I suggest you create a service that can handle encryption/decryption, and have the Message entity depend on it.
class Message
{
// ...
/**
* #var CryptService
*/
protected $crypt;
/**
* #param CryptService $crypt
*/
public function __construct(CryptService $crypt)
{
$this->crypt = $crypt;
}
}
Now you have to create Message entities by passing a CryptService to it. You can manage that in the service that creates Message entities.
But this will only take care of Message entities that you instantiate, not the ones Doctrine instantiates. For this, you can use the PostLoad event.
Create an event-listener:
class SetCryptServiceOnMessageListener
{
/**
* #var CryptService
*/
protected $crypt;
/**
* #param CryptService $crypt
*/
public function __construct(CryptService $crypt)
{
$this->crypt = $crypt;
}
/**
* #param LifecycleEventArgs $event
*/
public function postLoad(LifecycleEventArgs $event)
{
$entity = $args->getObject();
if ($entity instanceof Message) {
$message->setCryptService($this->crypt);
}
}
}
This event-listener will inject a CryptService into the Message entity whenever Doctrine loads one.
Register the event-listener in the bootstrap/configuration phase of your application:
$eventListener = new SetCryptServiceOnMessageListener($crypt);
$eventManager = $entityManager->getEventManager();
$eventManager->addEventListener(array(Events::postLoad), $eventListener);
Add the setter to the Message entity:
class Message
{
// ...
/**
* #param CryptService $crypt
*/
public function setCryptService(CryptService $crypt)
{
if ($this->crypt !== null) {
throw new \RuntimeException('We already have a crypt service, you cannot swap it.');
}
$this->crypt = $crypt;
}
}
As you can see, the setter safeguards against swapping out the CryptService (you only need to set it when none is present).
Now a Message entity will always have a CryptService as dependency, whether you or Doctrine instantiated it!
Finally we can use the CryptService to encrypt and decrypt the content:
class Message
{
// ...
/**
* #param string $content
*/
public function setContent($content)
{
$this->content = $this->crypt->encrypt($content);
}
/**
* #return string
*/
public function getContent()
{
return $this->crypt->decrypt($this->content);
}
}
Usage
In the view you can do something like this:
foreach ($thread->getSliceOfMessages(0, 10) as $message) {
echo $message->getContent();
}
As you can see this is dead simple!
Another pro is that the content can only exist in encrypted form in a Message entity. You can never accidentally store unencrypted content in the database.
The slice method's comment says:
Calling this method will only return the selected slice and NOT change the elements contained in the collection slice is called on.
So calling slice has no effect on the global PersistentCollection returned by your getMessages method: I don't think what you try to achieve here is doable.
As a workaround, you could declare a $availableMessages attribute in your Thread class, said attribute not being mapped to Doctrine. It would look like:
class Thread {
/**
* #var ArrayCollection
*/
protected $availableMessages;
...
public function __construct() {
...
$this->availableMessages = new ArrayCollection();
}
...
public function getAvailableMessages() {
return $this->availableMessages;
}
public function addAvailableMessage($m) {
$this->availableMessages->add($m);
}
...
}
When you process your messages in your service, you could:
$messages = $thread->getMessages()->slice(0, 10);
foreach ($messages as $message) {
//do your process...
...
//add the unpacked message to the proper "placeholder"
$thread->addAvailableMessage($message);
}
Then in your view:
echo $this->partialLoop(
'partial/thread/message.phtml',
$thread->getAvailableMessages()
);
There might be some differences in your implementation, like you might prefer having an ID-indexed array instead of an ArrayCollection for $availableMessages, and/or use a set instead of an add method, but you get the idea here...
Anyway, this logic allows you to control the amount of output messages from the service layer, without any implication of later-called layers, which is what you want from what I understood :)
Hope this helps!
I believe you should have a different class for decrypted message and push them separately into your view. Because Message is actually your entity-model and should be used for mapping data into your db but your purpose is quite different.
Because as I understood from your code you make smth. like:
$message->setText(decrypt($message->getText));
and after that you making even worse
$thread->setMessages(new ArrayCollection($thread->getMessages()->slice(0, 10)));
Imagine then, that after you made this changes, somewhere in the code $em->flush() happens.
You will loose every message except those 10, and they will be stored decrypted.
So you can push them as a separate array of decrypted messages (if you have only one thread on this view) or multi-dimensional array of messages with ThreadID as first level.
Or you can implement the answer Stock Overflaw gave you.
It's up to you, but you certainly should change your approach.
And by my opinion the best solution would be an implementation of decryption as ViewHelper.
It seems as if I figured it out. When calling slice, I get an array of entities. If I convert this array to an instance of \Doctrine\Common\Collections\ArrayCollection and call the setMessages method, it seems to work.
$messages = $thread->getMessages()->slice(0, 10);
foreach ($messages as $message) {
// Decrypt message
}
$thread->setMessages(new ArrayCollection($messages));
Then, in my view, I can just call $thread->getMessages() as I normally would. This has the advantage that my view does not need to know that any decryption is happening or know about any other properties. The result is that only one SQL query is executed, which is the one "generated by" slice - exactly what I wanted.

PHPUnit and specking method aliasing

Consider this class
class Foo {
public function alias_method($input) {
return $this->actual_method($input);
}
public function actual_method($input) {
# Do something
}
}
Now, I have already written tests that verify the behavior of actual_method, so for alias_method, all I want to ensure is that it calls actual_method with $input.
How can I do this?
As you've asked for a code-example, this is a PHPUnit test method body that has your expectation set-up already:
/**
* TODO Find out whether or not the test is necessary
*
* Note: This example is a slight adoption from the Observer/Subject
* mock example from PHPUnit docs:
* Example 9.11: Testing that a method gets called once and with
* a specified argument
*
* #link http://phpunit.de/manual/current/en/test-doubles.html
*
* #test
*/
public function methodIsCalledWithInputArgument()
{
// Create an Input object to test with as method argument
$input = new Input();
// Create a mock for the Foo class,
// only mock the actual_method() method.
$foo = $this->getMock('Foo', array('actual_method'));
// Set up the expectation for the actual_method() method
// to be called only once and with the argument $input
// as its parameter.
$foo->expects($this->once())
->method('actual_method')
->with($this->identicalTo$(input))
;
// Call the alias_method() method on the $foo object
// which we expect to call the mocked Foo object's
// actual_method() method with $input.
$foo->alias_method($input);
}

Passing an entire Class as a parameter within another Class

So far I feel like I've understood the concept and the advantages of OOP programming, and I've not really had any difficulties with understanding how to work with classes in PHP.
However, this has left me just a little confused. I think I may understand it, but I'm still uncertain.
I've been following a set of video tutorials (not sure on the rules on linking to outside resources, but I found them on youtube), and they're pretty self explanatory. Except, frustratingly, when the tutor decided to pass one class as a parameter within another class. At least I think that's what's happening;
Class Game
{
public function __construct()
{
echo 'Game Started.<br />';
}
public function createPlayer($name)
{
$this->player= New Player($this, $name);
}
}
Class Player
{
private $_name;
public function __construct(Game $g, $name)
{
$this->_name = $name;
echo "Player {$this->_name} was created.<br />";
}
}
Then I'm instantiating an object of the Game class and calling its method;
$game = new Game();
$game-> createPlayer('new player');
Rather frustratingly, the tutor doesn't really explain why he has done this, and hasn't displayed, as far as I can see, any calls in the code that would justify it.
Is the magic method constructor in Player passing in the Game class as a reference? Does this mean that the entire class is accessible within the Player class by reference? When referencing $this without pointing to any particular method or property, are you referencing the entire class?
If this is what is happening, then why would I want to do it? If I've created a Player inside my Game Class, then surely I can just access my Player Properties and Methods within the Game Class, right? Why would I want my Game Class inside my Player class as well? Could I then, for example, call createPlayer() within the Player class?
I apologise if my explanation has been at all confusing.
I guess my question boils down to; what is it that I'm passing as a parameter exactly, and why would I want to do it in every day OOP programming?
It's called type hinting and he's not passing the entire class as a parameter but ratter hinting the Class Player about the type of the first parameter
PHP 5 introduces type hinting. Functions are now able to force parameters to be objects (by specifying the name of the class in the function prototype), interfaces, arrays (since PHP 5.1) or callable (since PHP 5.4). However, if NULL is used as the default parameter value, it will be allowed as an argument for any later call.
(Extracted from php manual)
Does this mean that the entire class is accessible within the Player class by reference?
Not the entire class, but you can access the an instance of the class you are passing as a parameter
The method DOES expect to get the an object which is an instance of Game anything else, and it will error out.
You are passing an instance of Game just here: New Player($this, $name); The key word $this refers to the object instance you are in.
And last....I (and nobody else for that matter) has any idea why the author did it, as he is not using the Game instance after he passes it.
Why would u pass a Instance of a class?
Imagine a Class that accepts Users as input and according to some logic does something with them. (No comments in code, as function name and class name are supposed to be self-explanatory)
class User{
protected $name,$emp_type,$emp_id;
protected $department;
public function __construct($name,$emp_type,$emp_id){
$this->name = $name;
$this->emp_type = $emp_type;
$this->emp_id = $emp_id;
}
public function getEmpType(){
return $this->emp_type;
}
public function setDep($dep){
$this->department = $dep;
}
}
class UserHub{
public function putUserInRightDepartment(User $MyUser){
switch($MyUser->getEmpType()){
case('tech'):
$MyUser->setDep('tech control');
break;
case('recept'):
$MyUser->setDep('clercks');
break;
default:
$MyUser->setDep('waiting HR');
break;
}
}
}
$many_users = array(
0=>new User('bobo','tech',2847),
1=>new User('baba','recept',4443), many more
}
$Hub = new UserHub;
foreach($many_users as $AUser){
$Hub->putUserInRightDepartment($AUser);
}
/**
* Game class.
*/
class Game implements Countable {
/**
* Collect players here.
*
* #var array
*/
private $players = array();
/**
* Signal Game start.
*
*/
public function __construct(){
echo 'Game Started.<br />';
}
/**
* Allow count($this) to work on the Game object.
*
* #return integer
*/
public function Count(){
return count($this->players);
}
/**
* Create a player named $name.
* $name must be a non-empty trimmed string.
*
* #param string $name
* #return Player
*/
public function CreatePlayer($name){
// Validate here too, to prevent creation if $name is not valid
if(!is_string($name) or !strlen($name = trim($name))){
trigger_error('$name must be a non-empty trimmed string.', E_USER_WARNING);
return false;
}
// Number $name is also not valid
if(is_numeric($name)){
trigger_error('$name must not be a number.', E_USER_WARNING);
return false;
}
// Check if player already exists by $name (and return it, why create a new one?)
if(isset($this->players[$name])){
trigger_error("Player named '{$Name}' already exists.", E_USER_NOTICE);
return $this->players[$name];
}
// Try to create... this should not except but it's educational
try {
return $this->players[$name] = new Player($this, $name);
} catch(Exception $Exception){
// Signal exception
trigger_error($Exception->getMessage(), E_USER_WARNING);
}
// Return explicit null here to show things went awry
return null;
}
/**
* List Players in this game.
*
* #return array
*/
public function GetPlayers(){
return $this->players;
}
/**
* List Players in this game.
*
* #return array
*/
public function GetPlayerNames(){
return array_keys($this->players);
}
} // class Game;
/**
* Player class.
*/
class Player{
/**
* Stores the Player's name.
*
* #var string
*/
private $name = null;
/**
* Stores the related Game object.
* This allows players to point to Games.
* And Games can point to Players using the Game->players array().
*
* #var Game
*/
private $game = null;
/**
* Instantiate a Player assigned to a Game bearing a $name.
* $game argument is type-hinted and PHP makes sure, at compile time, that you provide a proper object.
* This is compile time argument validation, compared to run-time validations I do in the code.
*
* #param Game $game
* #param string $name
* #return Player
*/
public function __construct(Game $game, $name){
// Prevent object creation in case $name is not a string or is empty
if(!is_string($name) or !strlen($name = trim($name))){
throw new InvalidArgumentException('$name must be a non-empty trimmed string.');
}
// Prevent object creation in case $name is a number
if(is_numeric($name)){
throw new InvalidArgumentException('$name must not be a number.');
}
// Attach internal variables that store the name and Game
$this->name = $name;
$this->game = $game;
// Signal success
echo "Player '{$this->name}' was created.<br />";
}
/**
* Allow strval($this) to return the Player name.
*
* #return string
*/
public function __toString(){
return $this->name;
}
/**
* Reference back to Game.
*
* #return Game
*/
public function GetGame(){
return $this->game;
}
/**
* Allow easy access to private variable $name.
*
* #return string
*/
public function GetName(){
return $this->name;
}
} // class Player;
// Testing (follow main comment to understand this)
$game = new Game();
$player1 = $game->CreatePlayer('player 1');
$player2 = $game->CreatePlayer('player 2');
var_dump(count($game)); // number of players
var_dump($game->GetPlayerNames()); // names of players
Rewrote your code in a nicer way and added some missing variables that made that code pointless:
In player class you don't store the game.
In game class, you support only one player.
No error checking... anywhere.
Fixed all those plus:
Added exceptions (to prevent object creation)
Try{} catch(...){} Exception handling any OOP dev should know
Implemented Countable interface to allow count($game) players
Some more tricks that will give you a good read
Follow the comments and I hope your code will make more sense after you read it.

Does this PHPUnit test make any sense (or I'm testing the framework/PHP)?

I'm just beginning with PHPUnit and TDD.
Among others, I can't really answer to this question: Is this a good test? Am i actually testing my code or something already tested (i.e. the framework or PHP itself)?
Little example, this is the test subject:
class DateMax extends Constraint
{
/**
* #var string
*/
public $limit;
/**
* #var string
*/
private $invalidLimit = 'Option "limit" should be a valid date/time string.';
public function __construct($options = null)
{
parent::__construct($options);
if(false === strtotime($this->limit)) {
throw new InvalidOptionsException($this->invalidLimit, ['limit']);
}
}
}
I want to test that InvalidOptionsException is expected when invalid "limit" options are passed, otherwise $constraint->limit holds the correct value:
/**
* #dataProvider getInvalidLimits
* #expectedException InvalidOptionsException
*/
public function testInvalidLimits($testLimit)
{
new DateMax($testLimit);
}
/**
* #dataProvider getValidLimits
*/
public function testValidLimits($testLimit)
{
$constraint = new DateMax($testLimit);
$this->assertEquals($testLimit, $constraint->limit);
}
/**
* #return array[]
*/
public function getInvalidLimits()
{
return array(array('invalid specification'), array('tomorr'));
}
/**
* #return array[]
*/
public function getValidLimits()
{
return array(array('now'), array('+1 day'),array('last Monday'));
}
So question is does this make any sense or I'm testing the framework/PHP itself?
Of course it has sense, because you override constructor of Constraint class and there is possibility that you'll break something inside it. So basing on your constructor logic basically you want to test two things:
check if you call parent's constructor with the same options, exactly once (you can use mock for this purpose, you don't care about setting appropriate limit value, because this should be tested in Constraint class)
check if an appropriate exception has been thrown when limit has wrong value (eg. null)
edit: Some use case where first test will be useful may be this one:
Let say at some moment you want to extend your DateMax constructor in this way:
public function __construct($options = null)
{
$this->optionsWithDecrementedValues = $this->doWeirdThings($options);
parent::__construct($options);
if(false === strtotime($this->limit)) {
throw new InvalidOptionsException($this->invalidLimit, ['limit']);
}
}
but for example you didn't notice that method "doWeirdThings" takes a reference as argument. So in fact it changes $options value, what you didn't expect, but first test fails so you won't miss it.

Categories