So have a function that does something like this:
function mymod_init()
{
$ip = '123.123.123.123';
$newPath = mymod_redirect_calculate($ip);
if (!empty($newPath)) drupal_goto($newPath);
}
This completely breaks unit testing. I have tests for the "mymod_redirect_calculate", but if I add the above to my init function as shown, the tests can't run.
From what I have gathered "exit" and "drupal_goto" breaks unit testing.
How do I get around this?
Actually drupal_goto() ends up calling exit(). Using header() should work :
function mymod_init() {
$ip = '123.123.123.123';
$newPath = mymod_redirect_calculate($ip);
if (!empty($newPath)) {
$url = url($newPath, array('absolute' => TRUE));
header('Location: ' . $url, TRUE);
}
}
Related
I'm trying to write test code for monosilic code like below.
Q1. How to write test code which has access to DB?
Q2. How to refactor these code testable?
Q3. Is there any way to write test code with fewer change to production code?
I need your help!
Thanks!!
Example Production Code)
<?
class Sample_Model_Service_A
{
private $_result
private $_options
private $_someValue
public function __construct($params, $ids, $data) {
$this->_options = Sample_Model_Service_B::getOption($data);
}
private function setSomeValue() {
// some code shaping $_params to $someValue with $this->_options
$this->_someValue= $someValue;
}
// want to write test for this function
// changed this function's logic
private function setResult() {
// some code shaping $_someValue to $result
$this->_result = $result;
}
public function getter() {
retrn $this->_result;
}
}
?>
<?
class Sample_Model_Service_B
{
// get option from DB
public static function getOption($data) {
$dao = new Model_Dao_Option();
$option = $dao->getOption($data['id']);
return $option;
}
}
?>
My Test Code so far)
public function testsetResult()
{
// just make sure these variables are defined
$params = $ids = $data = [];
// try to make test for private function
$sample = new Sample_Model_Service_A($params, $ids, $data);
$reflection = new ReflectionClass($sample);
// get Method
$method = $reflection->getMethod('setresult');
$method->setAccessible(true);
// wondering how to get $result
$result = $method->invoke($sample);
// assert
$this->assertSame($result);
}
Mockery solved my issue.
Sample Code)
/**
* #dataProvider sampleProvider
*/
public function testsetResult($sampleData)
{
// mock Sample_Model_Service_B
$mockSample_Model_Service_B = Mockery::mock('alias:' . Sample_Model_Service_B::class);
$mockSample_Model_Service_B->shouldReceive('getOption')->andReturn($sampleData['option']);
$sample = new Sample_Model_Service_A($sampleData['params'], $sampleData['ids'], $sampleData['data']);
$sample->setResult();
$result = $sample->getter();
// assert
$this->assertSame($result, $sampleData['result']);
}
I'm working on a function to try some regex. Let me explain.
function traitement
{
if ($Matches.NAME -match "^A_(?<test1>[\w{1,6}]{1,7})")
{
[void]($memberOfCollection.add($Matches.test1))
}
elseif ($Matches.NAME -match "^A_(?<test2>[]*)")
{
[void]($memberOfCollection.add($Matches.test2))
}
else
{
[void]($memberOfCollection.add($Matches.NAME))
}
}
I have $Matches.NAME return string like "A_UserINTEL", "A_UserINTELASUS" or "A_UserINTEL_Adobe"
I need to differentiate 2 strings coming from $Matches.NAME and therefore write several tests.
"A_UserINTEL" and "A_UserINTELASUS" must return "UserINTEL".
"A_UserINTEL_Adobe" must return "UserINTEL_Adobe"
Test1 allows me to retrieve "UserINTEL" but I didn't succeed test2 to bring me "UserINTEL_Adobe".
Any idea? Thank you.
There's a;ways more ways then just one, especially when it comes to regular expressions, but here's one way:
function traitement {
# just for more clarity in the rest of the code
$name = $Matches.NAME
if ($name -match '^A_UserIntel(?:ASUS)?$') {
# the regex tests for "A_UserINTEL" or "A_UserINTELASUS"
[void]($memberOfCollection.add("UserINTEL"))
}
elseif ($name -match '^A_UserIntel_Adobe$') {
# this elseif is basically the same as
# elseif ($name -eq 'A_UserIntel_Adobe') {
# no real need for regex there..
[void]($memberOfCollection.add("UserINTEL_Adobe"))
}
else {
[void]($memberOfCollection.add($name))
}
}
I have a function which looks like the one written below. I need to write a unit test for the below function. I am not able to mock few values.
use File::Basename;
use File::Copy;
use File::Temp qw(tempdir);
our $CONFIG="/home/chetanv/svf.xml";
copyConfigFiles();
sub copyConfigFiles {
my $temp_dir = File::Temp->newdir();
my $targetpath = dirname("$CONFIG");
`sudo touch $tempdir/myfile`;
make_path($targetpath) if ( ! -d $targetpath );
File::Copy::copy("$temp_dir/myfile", $targetpath) or print "Problem copying file";
}
I have written the below unit test for the same below. I tried mocking "makepath" which does not seem to work.
subtest _setup(testname => "test copyConfigFiles") => sub {
my $CONFIG = "/my/dir/with/file.xml";
my $mockfileobj = Test::MockModule->new("File::Temp", no_auto => 1);
$mockfileobj->mock('newdir', sub { return "/tmp/delme"; } );
my $amockfileobj = Test::MockModule->new("File::Path", no_auto => 1);
$amockfileobj->mock('makepath', sub { return 0; } );
lives_ok { copyConfigFiles () } 'test copyConfigFiles OK';
done_testing();
};
The problem is i am not able to mock the below lines.
make_path($targetpath) if ( ! -d $targetpath );
File::Copy::copy("$temp_dir/myfile", $targetpath) or print "Problem copying file";
Any help on how i can mock the makepath function which is perl specific? I also tried to create a temporary directory and mock the global CONFIG file with the mocked file. Didn't seem to work.
If I ignore the code that can't be run because the context is missing and focus only on the two functions that you want mocked, one can do this by temporarily replacing the subs in the symbol table with local.
use warnings;
use strict;
use Data::Dump;
use File::Path qw/make_path/;
use File::Copy;
sub to_be_mocked {
my $targetpath = '/tmp/foo';
make_path($targetpath) if ! -d $targetpath;
File::Copy::copy("file.xml", $targetpath) or die;
}
sub run_with_mock {
no warnings 'redefine';
local *make_path = sub { dd 'make_path', #_; return 1 };
local *File::Copy::copy = sub { dd 'copy', #_; return 1 };
to_be_mocked();
}
run_with_mock();
__END__
# Output:
("make_path", "/tmp/foo")
("copy", "file.xml", "/tmp/foo")
Note that -d apparently can't be mocked, at least not directly.
I am new to Vtiger CRM. I want to write php code in log4php.properties file and also it need to be executed.
I can write the code but it is not executing at all. So kindly help me with a way which will allow to execute the file.
Also this need to be executed dynamic with separate domains.
Thanks
Open your index.php file from crm root directory and Add this code
function replace_string_in_a_file($filepath, $search, $replace) {
if (#file_exists($filepath)) {
$file = file($filepath);
foreach ($file as $index => $string) {
if (strpos($string, $search) !== FALSE)
$file[$index] = "$replace\n";
}
$content = implode($file);
return $content;
}else {
return NULL;
}
}
$filepath = $root_directory . 'log4php.properties';
$search = 'log4php.appender.A1.File=';
$replace = 'log4php.appender.A1.File=' . DOMAIN_PATH . '/logs/vtigercrm.log';
$log_properties_content = replace_string_in_a_file($filepath, $search, $replace);
if (!empty($log_properties_content)) {
file_put_contents($filepath, $log_properties_content);
}
I'm a bit new to Laravel unit testing. I need to get different outputs by calling same repo function for the unit testing.
So far my test is like this:
public function testReportOffdayWorked()
{
$input = [
'from_date' => '2016/01/01',
'to_date' => '2016/01/03',
];
$webServiceRepositoryMock = Mockery::mock('App\Repositories\WebServiceRepository');
$webServiceRepositoryMock->shouldReceive('callGet')->twice()->andReturn($this->issues);
$this->app->instance('App\Repositories\WebServiceRepository', $webServiceRepositoryMock);
$this->call('post', '/reporting/portal/report-offdays', $input);
$this->assertResponseOk();
$this->assertTrue($this->response->original->getName() == "Reporting::report_offday_worked");
}
I would like to get two different outputs for callGet function.
Set up a sequence of return values or closures for callGet().
andReturn(value1, value2, ...)
Sets up a sequence of return values or closures. For example, the first call will return value1 and the second value2. Note that all subsequent calls to a mocked method will always return the final value (or the only value) given to this declaration.
— docs.mockery
The following shows how to do it in PHPUnit mocks and mockery.
<?php
class The {
public function answer() { }
}
class MockingTest extends \PHPUnit_Framework_TestCase
{
public function testMockConsecutiveCalls()
{
$mock = $this->getMock('The');
$mock->expects($this->exactly(2))
->method('answer')
->will($this->onConsecutiveCalls(4, 2));
$this->assertSame(4, $mock->answer());
$this->assertSame(2, $mock->answer());
}
public function testMockeryConsecutiveCalls()
{
$mock = Mockery::mock('The');
$mock->shouldReceive('answer')->andReturn(4, 2);
$this->assertSame(4, $mock->answer());
$this->assertSame(2, $mock->answer());
}
}
How about using PHPUnit mocking framework?
$mock = $this->getMock('ClassName');
$mock->expects($this->at(0))
->method('getInt')
->will($this->returnValue('one'));
$mock->expects($this->at(1))
->method('getInt')
->will($this->returnValue('two'));
echo $mock->getInt(); //will return one
echo $mock->getInt(); //will return two