1

I wanted to know that can we create a phpunit mock when we do not know initially the number of arguments for the method Normally we would do something like this when we know the number of method invocations

mockResponse->expects($this->exactly(2))
    -> method('tmpFunc')
    ->withConsecutive(['header1'], ['header2']);

What I would like to do is get it to be something more dynamic

function mockMethod($n, $params) // $params is an array of strings
{
    $mockResponse = $this->getMockBuilder('PMA\libraries\Response')
        ->disableOriginalConstructor()
        ->setMethods(array('tempFunc', 'headersSent'))
        ->getMock();

    if($n > 1)
    {
        $mockResponse->expects($this->exactly($n))
            ->method('tempFunc')
            ->withConsecutive( //todo );

        $mockResponse->expects($this->any())
            ->method('headersSent')
            ->with()
            ->will($this->returnValue(false));

    }
}

So for example if $n = 2 and $params = array('HTTP/1.1 303 See Other', 'Location: index.php?lang=en') then the function should do this

$mockResponse = $this->getMockBuilder('PMA\libraries\Response')
        ->disableOriginalConstructor()
        ->setMethods(array('tempFunc', 'headersSent'))
        ->getMock();

$mockResponse->expects($this->exactly($n))
    ->method('tempFunc')
    ->withConsecutive([$params[1]], [$params[2]]);

$mockResponse->expects($this->any())
        ->method('headersSent')
        ->with()
        ->will($this->returnValue(false));

How should I replace the todo so that if $n = 2 then each string will be sent as an argument to tempFunc().

public function tempFunc($text)
{
    header($text);
}

public function headersSent()
{
    return headers_sent();
}
osaid
  • 55
  • 10
  • Can you post the actual code for `tempFunc()` ? – John Joseph Jan 04 '17 at 09:59
  • @JohnJoseph tempFunc is in another file located in a different directory – osaid Jan 04 '17 at 10:29
  • Is that the actual code? As there is only one argument to that function. Show the code where these unknown parameters are declared/handled in the actual function. It doesn't matter that it's in a different file. – John Joseph Jan 04 '17 at 10:58
  • @JohnJoseph by number of arguments I meant number of calls to the function using the mock object as in `->withConsecutive( [arg1], [arg2], ... [argn] )`. Sorry I wrote `with` instead of `withConsecutive ` on my code – osaid Jan 04 '17 at 15:41
  • so what should tempFunc return ? something different if $n = 1? $n = 2? $n = 3 ?? – John Joseph Jan 04 '17 at 15:47
  • It shouldn't return anything . Normally we would do `with('some header')` but I want to do something like `withConsecutive([$params[0]], [$params[1]]...[$params[$n]] )` and $n, $params is passed as an argument to mockMethod function – osaid Jan 04 '17 at 17:50
  • Can you clarify what you are actually trying to test? Testing a method that returns nothing doesn't make sense. Can you post more code of what you expect to happen when calling `tempFunc` for the 1st time, 2nd time, 3rd time? there's not enough code in your question to follow what you are trying to do. – John Joseph Jan 05 '17 at 10:31
  • actually originally we used to do used runkit to test tempFunc() but now we need to remove the runkit dependencies and add mocking of the Response object (Response class contains tempFunc() ). – osaid Jan 05 '17 at 15:25
  • Can you add to your question what you expect the calls to `tempFunc` to actually do? It's not clear. I would expect `tempFunc` to return something different depending on what arguments are provided? If you can clarify if that is correct, then that is easy to solve. – John Joseph Jan 05 '17 at 15:36
  • @JohnJoseph when the mock is created it does the assertions that were done originally . So now since we need to remove these dependencies from a lot of files therefore I wanted to make a function so the same code doesn't need to be repeated. What I want in this function is to remove `$this->assertEquals(array('HTTP/1.1 303 See Other', 'Location: index.php?lang=en'),$GLOBALS['header']);` with `mockResponse(2,array('HTTP/1.1 303 See Other', 'Location: index.php?lang=en')` so it will automatically do as shown in code in question – osaid Jan 05 '17 at 15:44
  • @JohnJoseph this was the issue I was working on https://github.com/phpmyadmin/phpmyadmin/issues/12079 – osaid Jan 05 '17 at 15:46
  • The problem is, to give you an answer I need to know what your method **needs** to return under what **circumstances**. Your question does not make sense at all as-is. Either post more code to demonstrate what you **want** to do or explain what you **expect** it to do. – John Joseph Jan 05 '17 at 15:49
  • @JohnJoseph I have added some more code and I think it should make sense now – osaid Jan 05 '17 at 16:06
  • OK - what happens if $n = 1? $n = 3? $n = any other number? – John Joseph Jan 05 '17 at 16:13
  • for $n = 1 we will simply pass $params to with() method of $mockResponse else we for $n = 3 we use `withConsecutive([$params[0]], [$params[1]],[$params[2]]) similarly for $n = 4 – osaid Jan 05 '17 at 16:17
  • So `tempFunc` can take any number of string parameters? – John Joseph Jan 05 '17 at 16:19
  • My question originally is - can we have this kind of dynamism for $n > 1 and each $params gets added as a part of withConsecutive ? I am pretty sure the answer is no but I thought someone may be able to figure something out – osaid Jan 05 '17 at 16:20
  • no it cannot, the withConsecutive method allows us to test for different method invocation http://stackoverflow.com/questions/5988616/phpunit-mock-method-multiple-calls-with-different-arguments/23942979#23942979 – osaid Jan 05 '17 at 16:23
  • If you are not testing for the return value of `tempFunc`, I fail to see the point of mocking it at all. You are not actually testing anything. What assert* methods are you using in your test case? – John Joseph Jan 06 '17 at 09:26
  • This is the issue I am working on https://github.com/phpmyadmin/phpmyadmin/issues/12079 – osaid Jan 06 '17 at 16:30
  • again .... show in your code what you are testing for. All you have provided is the mock set up ... however, you cannot correctly determine the mock set up without knowing how you intend to use it and how you use it to make the test pass. Provide some actual assertions, pseudo code if needs be so we can see a full resolution of Arrange Act Assert. – John Joseph Jan 06 '17 at 16:41

1 Answers1

2

I finally got the answer from someone I knew

$header_method = $mockResponse->expects($this->exactly(count($param)))
            ->method('tmpFunc');
call_user_func_array(array($header_method, 'withConsecutive'), $param);
osaid
  • 55
  • 10