Bad exception message returned #4

Closed
frosty22 opened this Issue Mar 22, 2013 · 7 comments

Projects

None yet

3 participants

Hi,

I found bug in returned exception, when I have simple code:

        $obj = $mockista->create("Foo");
        $obj->expects("bar")->with(1)->once();
        $obj->bar(2);

I except message of exception:

Unexpected call in mock Foo::bar(), args: array (0 => 2)

but I get:

Expected method Foo::bar() should be called exactly once but not called at all.

But if I have same code, without checking calls count:

        $obj = $mockista->create("Foo");
        $obj->expects("bar")->with(1);
        $obj->bar(2);

returned message is correct!

Contributor
jasir commented Mar 22, 2013

Works for me, try to add this test:

public function test_issue_4() {
    $this->object->expects('bar')->with(1)->once();
    try {
        $this->object->bar(2);
        $this->object->assertExpectations();
    } catch (\Mockista\MockException $e) {
        $this->assertEquals("Unexpected call in mock unnammed::bar(), args: array (\n  0 => 2,\n)", $e->getMessage());
        return;
    }
    $this->fail('No exception thrown');
}

If you are able to write failing test, I would try to fix that.

So, I'm sorry it is error on my side ... I use your BaseTestCase sample, where Mockista\Registry is used and error is in "$this->mockista->assertExpectations()" call..

This crash - "Mockista\MockException: Expected method unnamed::bar() should be called exactly once but not called at all."

class MockerTest extends \Tester\TestCase
{

    /** @var \Mockista\Registry */
    protected $mockista;

    protected $object;


    protected function setUp()
    {
        $this->mockista = new \Mockista\Registry();
    }

    protected function tearDown()
    {
        $this->mockista->assertExpectations(); // When I comment this, test is correct!
    }


    public function testIssue4() {
        $this->object = $this->mockista->create();
        $this->object->expects('bar')->with(1)->once();
        try {
            $this->object->bar(2);
            $this->object->assertExpectations();
        } catch (\Mockista\MockException $e) {
            Assert::equal("Unexpected call in mock unnammed::bar(), args: array (\n  0 => 2,\n)", $e->getMessage());
            return;
        }
        $this->fail('No exception thrown');
    }


}

So it's really problem in Nette/Tester, I still don't know why and I suppose you don't use it. But in Nette/Tester is problem in TestCase (base class of all tests), in this method of TestCase:

    /**
     * Runs the single test.
     * @return void
     */
    public function runTest($name, array $args = array())
    {
        $this->setUp();
        try {
            call_user_func_array(array($this, $name), $args);
        } catch (\Exception $e) {
        }
        $this->tearDown();
        if (isset($e)) {
            throw $e;
        }
    }

This cause that is returned invalid exception: "Expected method unnamed::bar() should be called exactly once but not called at all."

But when I move calling tearDown method inside try/catch:

    /**
     * Runs the single test.
     * @return void
     */
    public function runTest($name, array $args = array())
    {
        $this->setUp();
        try {
            call_user_func_array(array($this, $name), $args);
            $this->tearDown();
        } catch (\Exception $e) {
        }

        if (isset($e)) {
            throw $e;
        }
    }

It throw correct exception ... it's magic :)

Contributor
jasir commented Mar 23, 2013

It seems that problem is that assertExpectations is called twice - first call "resets" the previous calls, hence this message.

Owner

If you call assertExpectations in tearDown method, you don't have to call it in your tests. It's called automatically for you.

@janmarek janmarek closed this Mar 23, 2013

I'm sorry, I placed bad sample code here. When I remove call "assertExpectations" in test's method, it still throw bad exception. For test I dumped mock in assertExpectations and it's really call only once, so there isn't problem. But problem really will be in implements with Nette/Tester.

Heureka! I found error, when method "bar" is called, it throw correct Exception with invalid arguments. But this exception is catch in "runTest" method. After it is call tearDown method and throw Exception with invalid count of calls, which isn't catch.

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