$this->at($index); bug? #674

Closed
TomBZombie opened this Issue Sep 29, 2012 · 13 comments

Comments

4 participants
@TomBZombie

I'm fairly sure this does not work as intended.

Consider this:

class Foo {
    public function bar($a) {

    }

    public function test() {

    }
}

With a test that does:

    $mock = $this->getMock('Foo');

    $mock->expects($this->at(0))->method('bar')->with(1);
    $mock->expects($this->at(1))->method('bar')->with(2);
    $mock->bar(1);
    $mock->bar(2);

This works exactly as intended/documented. "Returns a matcher that matches when the method it is evaluated for is invoked at the given $index."

However, if another method is called on the mock. For instance:

    $mock = $this->getMock('Foo');

    $mock->expects($this->at(0))->method('bar')->with(1);
    $mock->expects($this->at(1))->method('bar')->with(2);
    $mock->bar(1);
    $mock->test();
    $mock->bar(2);

The test now fails with an unhelpful error "Mocked method does not exist". It does exist and it works perfectly until the call to $mock->test().

Either the documentation needs to be updated to say that $index is the running count of the total number of methods called on the mock or the code needs updating to count on a per method basis.

As it stands, the test will fail based on implementation changes to the code being tested in which it shouldn't fail the test. I don't see why my second test should fail. It's still being called with the right parameters in the correct order. The fact that $mock->test() has been called is irrelevant.

As a bare minimum the returned error "mocked method does not exist" needs to be updated. It's both incorrect and misleading.

@TomBZombie TomBZombie closed this Sep 29, 2012

@TomBZombie TomBZombie reopened this Sep 29, 2012

@TomBZombie

This comment has been minimized.

Show comment
Hide comment
@TomBZombie

TomBZombie Sep 29, 2012

This is a working fix.

In PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex

    protected $indexes = array();
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        if (!isset($this->indexes[$invocation->methodName])) $this->indexes[$invocation->methodName] = 0;
        else $this->indexes[$invocation->methodName]++;
        $this->currentIndex++;

        return $this->indexes[$invocation->methodName] == $this->sequenceIndex;
    }

This is a working fix.

In PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex

    protected $indexes = array();
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        if (!isset($this->indexes[$invocation->methodName])) $this->indexes[$invocation->methodName] = 0;
        else $this->indexes[$invocation->methodName]++;
        $this->currentIndex++;

        return $this->indexes[$invocation->methodName] == $this->sequenceIndex;
    }

@TomBZombie TomBZombie referenced this issue in sebastianbergmann/phpunit-mock-objects Sep 30, 2012

Closed

at() matcher improvement #101

@edorian

This comment has been minimized.

Show comment
Hide comment
@edorian

edorian Sep 30, 2012

Contributor

Hi, thanks for the report.

This has been discussed various times and there should be a couple of closed bugs with longer discussions here and on mock-object.

Either the documentation needs to be updated to say that $index is the running count of the total number of methods called on the mock or the code needs updating to count on a per method basis.

Yeah, surely the wording on http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.mock-objects.tables.matchers could be improved or a note could be added. I'm open to suggestions.


The issue with the current ->at matcher is that there is no way at all for us to change it's behavior. Applying the fix you're suggesting (count per method and not on the class) breaks every test suite of every major php framework.

There is no question that the ->at matcher is ugly. The docs should maybe discourage it's usage more than they do and suggest alternatives ( http://stackoverflow.com/questions/5988616/phpunit-mock-method-multiple-calls-with-different-arguments ) but I hope it's clear that we can't just change it.

If anything we could add another matcher that works on a per method basis. I'm not sure if thats worth it, it surely would make certain scenarios easier to test and since the order of calls is sometimes important it might be worth considering it.

If order of all method calls really matters and should be tested (thats what at was for initially iirc (and to work around the fact that back then there where no alternatives for multi-method-calls)) at still would have to be used.

Contributor

edorian commented Sep 30, 2012

Hi, thanks for the report.

This has been discussed various times and there should be a couple of closed bugs with longer discussions here and on mock-object.

Either the documentation needs to be updated to say that $index is the running count of the total number of methods called on the mock or the code needs updating to count on a per method basis.

Yeah, surely the wording on http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.mock-objects.tables.matchers could be improved or a note could be added. I'm open to suggestions.


The issue with the current ->at matcher is that there is no way at all for us to change it's behavior. Applying the fix you're suggesting (count per method and not on the class) breaks every test suite of every major php framework.

There is no question that the ->at matcher is ugly. The docs should maybe discourage it's usage more than they do and suggest alternatives ( http://stackoverflow.com/questions/5988616/phpunit-mock-method-multiple-calls-with-different-arguments ) but I hope it's clear that we can't just change it.

If anything we could add another matcher that works on a per method basis. I'm not sure if thats worth it, it surely would make certain scenarios easier to test and since the order of calls is sometimes important it might be worth considering it.

If order of all method calls really matters and should be tested (thats what at was for initially iirc (and to work around the fact that back then there where no alternatives for multi-method-calls)) at still would have to be used.

@edorian edorian referenced this issue in sebastianbergmann/phpunit-documentation Sep 30, 2012

Closed

Document ->at($index) to reflect it's on "per-object" basis. #73

@edorian

This comment has been minimized.

Show comment
Hide comment
@edorian

edorian Sep 30, 2012

Contributor

For the doc part I've opened: sebastianbergmann/phpunit-documentation#73 and for the rest all i can say in the end "Sorry. It was designed that way, it's not nice but we can't change it now due to BC".

Hope thats fine with you and if you have a suggestion/PR for another matcher feel free to add it :)

Contributor

edorian commented Sep 30, 2012

For the doc part I've opened: sebastianbergmann/phpunit-documentation#73 and for the rest all i can say in the end "Sorry. It was designed that way, it's not nice but we can't change it now due to BC".

Hope thats fine with you and if you have a suggestion/PR for another matcher feel free to add it :)

@edorian edorian closed this Sep 30, 2012

@TomBZombie

This comment has been minimized.

Show comment
Hide comment
@TomBZombie

TomBZombie Sep 30, 2012

That's understandable but as I understand it, there's no way to test whether a method has been called multiple times without using at() unless the method returns a value.

Using exactly() requires that the method is called with the same parameters. Essentially I want to test that a method has been called multiple times with specific parameters. (e.g. in my example, a 1 then a 2. The order doesn't actually matter)

Either the documentation doesn't make it clear how this can be achieved or I can find no way to do it.

That's understandable but as I understand it, there's no way to test whether a method has been called multiple times without using at() unless the method returns a value.

Using exactly() requires that the method is called with the same parameters. Essentially I want to test that a method has been called multiple times with specific parameters. (e.g. in my example, a 1 then a 2. The order doesn't actually matter)

Either the documentation doesn't make it clear how this can be achieved or I can find no way to do it.

@TomBZombie

This comment has been minimized.

Show comment
Hide comment
@TomBZombie

TomBZombie Sep 30, 2012

After looking into it further, I believe the best way to achieve this would be to add a logicalEach() or similar:

    $mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))->method('foo')->with($this->logicalEach($this->equalTo(2), $this->equalTo(1)));
    $mock->foo(1);
    $mock->foo(2);

Which would check that the method 'foo' is called with each of the supplied constraints.

At the moment this can be achieved with logicalOr()

    $mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))->method('foo')->with($this->logicalOr($this->equalTo(2), $this->equalTo(1)));
    $mock->foo(1);
    $mock->foo(2);

However, it passes if foo is called with 1 twice, which isn't what I want to test.

I had a very quick try at implementing this:

class PHPUnit_Framework_Constraint_Each extends PHPUnit_Framework_Constraint_Or
{

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {   

        $success = FALSE;
        $constraint = NULL;

        foreach ($this->constraints as $key => $constraint) {
            if ($constraint->evaluate($other, $description, TRUE)) {
                $success = TRUE;
                unset($this->constraints[$key]);
                break;
            }
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

}

Which, in theory, should work. However I don't know enough about the internals of PHPUnit to know how it works. In this example above with a call to $mock->foo(1); then $mock->foo(2);, PHPUnit_Framework_Constraint_Each::evaluate() is called five times. Twice with 1 and three times with 2

Firstly: Do you think the addition of logicalEach() or something with a more appropriate name is the right approach? ->at() isn't ideal in a lot of cases because it exposes implementation details to the test.

Secondly: If so, why is evaluate called five times? I was expecting to see it called twice. Once for each call to $mock->foo()

Thanks for your time!

After looking into it further, I believe the best way to achieve this would be to add a logicalEach() or similar:

    $mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))->method('foo')->with($this->logicalEach($this->equalTo(2), $this->equalTo(1)));
    $mock->foo(1);
    $mock->foo(2);

Which would check that the method 'foo' is called with each of the supplied constraints.

At the moment this can be achieved with logicalOr()

    $mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))->method('foo')->with($this->logicalOr($this->equalTo(2), $this->equalTo(1)));
    $mock->foo(1);
    $mock->foo(2);

However, it passes if foo is called with 1 twice, which isn't what I want to test.

I had a very quick try at implementing this:

class PHPUnit_Framework_Constraint_Each extends PHPUnit_Framework_Constraint_Or
{

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {   

        $success = FALSE;
        $constraint = NULL;

        foreach ($this->constraints as $key => $constraint) {
            if ($constraint->evaluate($other, $description, TRUE)) {
                $success = TRUE;
                unset($this->constraints[$key]);
                break;
            }
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

}

Which, in theory, should work. However I don't know enough about the internals of PHPUnit to know how it works. In this example above with a call to $mock->foo(1); then $mock->foo(2);, PHPUnit_Framework_Constraint_Each::evaluate() is called five times. Twice with 1 and three times with 2

Firstly: Do you think the addition of logicalEach() or something with a more appropriate name is the right approach? ->at() isn't ideal in a lot of cases because it exposes implementation details to the test.

Secondly: If so, why is evaluate called five times? I was expecting to see it called twice. Once for each call to $mock->foo()

Thanks for your time!

@edorian

This comment has been minimized.

Show comment
Hide comment
@edorian

edorian Sep 30, 2012

Contributor

Oh. Quite nice idea!

I was thinking about something like $mock->expects($this->atMethod but your idea is really nice too :)

Your implementation doesn't depend on the order of arguments but just makes sure each one would get passed once.

Maybe another idea/name could also be $this->logicalOnConsecutiveCalls to match the $this->OnConsecutiveCalls()) return but logicalEach sounds very nice and short indeed. I'm just not sure if "pick any of those but just once" is specific enough (when it comes to multiple method parameters there might be strange results?).

For the implementation part:

I'm not fluent in the mock object lib myself but I've tried it myself and i also get 5 calls to the object. No immediate clue why though and digging through the backtraces and figuring out the code and how it's resolved will take some time.

In general i like your proposal even so I'm not sure if:

->with(
    $this->logcialEach(1,2,3),
    $this->logcialEach(1,2,3)
);

should match

$object->method(1,2); 
$object->method(3,1); 
$object->method(2,3); 

or rather just strictly

$object->method(1,1); 
$object->method(2,2); 
$object->method(3,3); 
Contributor

edorian commented Sep 30, 2012

Oh. Quite nice idea!

I was thinking about something like $mock->expects($this->atMethod but your idea is really nice too :)

Your implementation doesn't depend on the order of arguments but just makes sure each one would get passed once.

Maybe another idea/name could also be $this->logicalOnConsecutiveCalls to match the $this->OnConsecutiveCalls()) return but logicalEach sounds very nice and short indeed. I'm just not sure if "pick any of those but just once" is specific enough (when it comes to multiple method parameters there might be strange results?).

For the implementation part:

I'm not fluent in the mock object lib myself but I've tried it myself and i also get 5 calls to the object. No immediate clue why though and digging through the backtraces and figuring out the code and how it's resolved will take some time.

In general i like your proposal even so I'm not sure if:

->with(
    $this->logcialEach(1,2,3),
    $this->logcialEach(1,2,3)
);

should match

$object->method(1,2); 
$object->method(3,1); 
$object->method(2,3); 

or rather just strictly

$object->method(1,1); 
$object->method(2,2); 
$object->method(3,3); 
@TomBZombie

This comment has been minimized.

Show comment
Hide comment
@TomBZombie

TomBZombie Sep 30, 2012

I think the second one or tests become far too vague. Perhaps rather than logicalEach it should be named logicalSequence or your suggestion of logicalOnConsecutiveCalls which also implies the parameters are called in a sequence.

Implementation wise, I've tracked down two of the extra calls. In PHPUnit_Framework_MockObject_Matcher_Parameters::matches() it calls $this->verify() which is what is calling PHPUnit_Framework_Constraint_Each::evaluate() . I can't see the reasoning behind calling $this->verify() in matches() though.

I haven't been able to track down the final call to PHPUnit_Framework_Constraint_Each::evaluate(), however.

I think the second one or tests become far too vague. Perhaps rather than logicalEach it should be named logicalSequence or your suggestion of logicalOnConsecutiveCalls which also implies the parameters are called in a sequence.

Implementation wise, I've tracked down two of the extra calls. In PHPUnit_Framework_MockObject_Matcher_Parameters::matches() it calls $this->verify() which is what is calling PHPUnit_Framework_Constraint_Each::evaluate() . I can't see the reasoning behind calling $this->verify() in matches() though.

I haven't been able to track down the final call to PHPUnit_Framework_Constraint_Each::evaluate(), however.

@TomBZombie

This comment has been minimized.

Show comment
Hide comment
@TomBZombie

TomBZombie Sep 30, 2012

Here's an incredibly crude workaround. It's the same as before but keeps track of the number of calls to evaluate(). While this ensures compatibility with all existing code and is entirely self-contained, it's rather brittle. If evaluate() gets called additional/fewer times it'll stop working as intended. That said... it does work:

class PHPUnit_Framework_Constraint_Each extends PHPUnit_Framework_Constraint_Or
{

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */

    protected $called = array(); 

    public function evaluate($other, $description = '', $returnResult = FALSE)
    {   

        $constraint = NULL;

        $success = (count($this->constraints) == 0);

        foreach ($this->constraints as $key => $constraint) {
            if ($constraint->evaluate($other, $description, TRUE)) {
                $success = TRUE;                    

                $objStr = is_scalar($other) ? $other : md5(serialize($other));
                if (!isset($this->called[$objStr])) $this->called[$objStr] = 0;

                $this->called[$objStr]++;
                if ($this->called[$objStr] == 2) {      
                    unset($this->constraints[$key]);
                }

                break;
            }
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

}

Some test code.

This passes:

$mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))->method('foo')->with($this->logicalEach($this->equalTo(1), $this->equalTo(2)));
    $mock->foo(1);
    $mock->foo(2);

This fails:

$mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))->method('foo')->with($this->logicalEach($this->equalTo(1), $this->equalTo(2)));
    $mock->foo(1);
    $mock->foo(1);

As I said it's very crude but it does work. I'll play around with how it can work with multiple parameters.

Edit: The example above works as you'd specified in your first less strict example

This passes:

$mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))
         ->method('foo')
         ->with(
            $this->logicalEach($this->equalTo(1), $this->equalTo(2)),
            $this->logicalEach($this->equalTo(1), $this->equalTo(2))
            );
    $mock->foo(1,1);
    $mock->foo(2,2);

As does:

    $mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))
         ->method('foo')
         ->with(
            $this->logicalEach($this->equalTo(1), $this->equalTo(2)),
            $this->logicalEach($this->equalTo(1), $this->equalTo(2))
            );
    $mock->foo(1,2);
    $mock->foo(2,1);

Whereas this doesn't:

    $mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))
         ->method('foo')
         ->with(
            $this->logicalEach($this->equalTo(1), $this->equalTo(2)),
            $this->logicalEach($this->equalTo(1), $this->equalTo(2))
            );
    $mock->foo(1,2);
    $mock->foo(2,2);

I'm not quite sure how I can change it to allow for the stricter variant you mentioned because to do that, I believe each logicalEach() would need access to the other logicalEach().

If you or anyone else can point me in the right direction that'd be great! I'd be interested to see others opinions on this idea as well.

Here's an incredibly crude workaround. It's the same as before but keeps track of the number of calls to evaluate(). While this ensures compatibility with all existing code and is entirely self-contained, it's rather brittle. If evaluate() gets called additional/fewer times it'll stop working as intended. That said... it does work:

class PHPUnit_Framework_Constraint_Each extends PHPUnit_Framework_Constraint_Or
{

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */

    protected $called = array(); 

    public function evaluate($other, $description = '', $returnResult = FALSE)
    {   

        $constraint = NULL;

        $success = (count($this->constraints) == 0);

        foreach ($this->constraints as $key => $constraint) {
            if ($constraint->evaluate($other, $description, TRUE)) {
                $success = TRUE;                    

                $objStr = is_scalar($other) ? $other : md5(serialize($other));
                if (!isset($this->called[$objStr])) $this->called[$objStr] = 0;

                $this->called[$objStr]++;
                if ($this->called[$objStr] == 2) {      
                    unset($this->constraints[$key]);
                }

                break;
            }
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

}

Some test code.

This passes:

$mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))->method('foo')->with($this->logicalEach($this->equalTo(1), $this->equalTo(2)));
    $mock->foo(1);
    $mock->foo(2);

This fails:

$mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))->method('foo')->with($this->logicalEach($this->equalTo(1), $this->equalTo(2)));
    $mock->foo(1);
    $mock->foo(1);

As I said it's very crude but it does work. I'll play around with how it can work with multiple parameters.

Edit: The example above works as you'd specified in your first less strict example

This passes:

$mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))
         ->method('foo')
         ->with(
            $this->logicalEach($this->equalTo(1), $this->equalTo(2)),
            $this->logicalEach($this->equalTo(1), $this->equalTo(2))
            );
    $mock->foo(1,1);
    $mock->foo(2,2);

As does:

    $mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))
         ->method('foo')
         ->with(
            $this->logicalEach($this->equalTo(1), $this->equalTo(2)),
            $this->logicalEach($this->equalTo(1), $this->equalTo(2))
            );
    $mock->foo(1,2);
    $mock->foo(2,1);

Whereas this doesn't:

    $mock = $this->getMock('stdClass', array('foo'));
    $mock->expects($this->exactly(2))
         ->method('foo')
         ->with(
            $this->logicalEach($this->equalTo(1), $this->equalTo(2)),
            $this->logicalEach($this->equalTo(1), $this->equalTo(2))
            );
    $mock->foo(1,2);
    $mock->foo(2,2);

I'm not quite sure how I can change it to allow for the stricter variant you mentioned because to do that, I believe each logicalEach() would need access to the other logicalEach().

If you or anyone else can point me in the right direction that'd be great! I'd be interested to see others opinions on this idea as well.

@edorian

This comment has been minimized.

Show comment
Hide comment
@edorian

edorian Oct 1, 2012

Contributor

Thanks for your work that far :) I hope to get around to digger depper soonish. Maybe @sebastianbergmann could also give some pointers :)

Contributor

edorian commented Oct 1, 2012

Thanks for your work that far :) I hope to get around to digger depper soonish. Maybe @sebastianbergmann could also give some pointers :)

@pscheit

This comment has been minimized.

Show comment
Hide comment
@pscheit

pscheit Feb 5, 2013

Contributor

ah i know that deep digging in the issues would do the trick :)

i'm +1 for that or anything that helps getting around the at() thingy ..

Contributor

pscheit commented Feb 5, 2013

ah i know that deep digging in the issues would do the trick :)

i'm +1 for that or anything that helps getting around the at() thingy ..

@pscheit

This comment has been minimized.

Show comment
Hide comment
@pscheit

pscheit Feb 6, 2013

Contributor

I implemented a atMethod($method, $index)
which filters the counts to currentIndex with the given $method.

its a little verbose, because you would write:

$mock->expects($this->atMethod('doSomething', 0))->method('doSomething')

Should i send a pull request to MockObjects?

Contributor

pscheit commented Feb 6, 2013

I implemented a atMethod($method, $index)
which filters the counts to currentIndex with the given $method.

its a little verbose, because you would write:

$mock->expects($this->atMethod('doSomething', 0))->method('doSomething')

Should i send a pull request to MockObjects?

@XedinUnknown

This comment has been minimized.

Show comment
Hide comment
@XedinUnknown

XedinUnknown Mar 1, 2018

Incredibly sorry to ping all of the honorable participants, but I still don't understand how to achieve this, 5 years later. If it was down to returning values every time, then maybe I could do with withConsecutive() and returnValueMap(). However, my method needs to throw on one of the invocations. @pscheit, was your fix ever incorporated, and if so - where?

Incredibly sorry to ping all of the honorable participants, but I still don't understand how to achieve this, 5 years later. If it was down to returning values every time, then maybe I could do with withConsecutive() and returnValueMap(). However, my method needs to throw on one of the invocations. @pscheit, was your fix ever incorporated, and if so - where?

@pscheit

This comment has been minimized.

Show comment
Hide comment
@pscheit

pscheit Mar 1, 2018

Contributor

No, it wasn't incorporated. I implemented my own expectation in phpunit, but was never very happy with it.

Just use mockery/mockery for this

Contributor

pscheit commented Mar 1, 2018

No, it wasn't incorporated. I implemented my own expectation in phpunit, but was never very happy with it.

Just use mockery/mockery for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment