Difference Stub Fixture
Asked Answered
G

1

7

I am learning codeception and I wonder what is the difference between stubs and fixtures. Both help me to load well-defined data and kepp tessts simple.

But when do I use \Codeception\Util\Stub and when do I use \Codeception\Util\Fixtures

Guerin answered 27/1, 2017 at 17:29 Comment(0)
A
7

So a stub is what Codeception uses to mock objects. In short, mocking is creating objects that simulate the behaviour of real objects.

Here is an example:

class UpdateBalance
{
    public $balanceRepository;

    public function __construct(BalanceRepositoryInterface $balanceRepository)
    {
        $this->balanceRepository = $balanceRepository; 
    }

    public function subtract($amount, $id)
    {
        $updatedAmount = $this->balanceRepository->subtract($amount, $id);

        if ($updatedAmount < 0) {
            throw NegativeBalanceException($updatedAmount, $id);
        }

        return $updatedAmount;

    }
}


class UpateBalanceTest extends PHPUnit_Framework_TestCase
{
    public function testSubtractThrowsNegativeBalanceException()
    {

        $balanceRepository = Stub::make(
           'BalanceRepositoryInterface'
            array(
                'subtract' => Stub::atLeastOnce(function() { return -100 })
            )
        );


        $updateBalance = new UpdateBalance($balanceRepository);

        $this->expectException(NegativeBalanceException::class);

        $updateBalance->subtract(100, 1);


    }
}

Note that we don't have a BalanceRepsository class. We have used Codeception stubs and pretended that the BalanceRepository class exists. By pretending it exists we can test the functionality of the UpdateBalance::subtract function by checking that the NegativeBalanceException is thrown.

Fixtures on the other hand would be for sharing test data throughout all your tests. If we use the UpdateBalance::subtract() example again, we could stress test the amount field ensuring it throws the correct exception depending on the amount being passed through:

// In some bootstrap or setup function
Fixtures::add('zero-amount', 0);
Fixtures::add('negative-amount', -1);
Fixtures::add('string-negative-amount', '-1');




class UpdateBalance
{
    // ...

    public function subtract($amount, $id)
    {
        if ($amount < 0) {
            throw new 
        }

        // ...

    }
}


class UpateBalanceTest extends PHPUnit_Framework_TestCase
{

    // ...

    public function testSubtractThrowsCantSubtractNegativeAmountException()
    {

        $balanceRepository = Stub::make(
           'BalanceRepositoryInterface'
        );


        $updateBalance = new UpdateBalance($balanceRepository);

        $this->expectException(CantSubtractNegativeAmountException::class);

        $updateBalance->subtract(Fixture::get('negative-amount'), 1);


    }
}

Now we can use our pre-defined fixtures throughout all our tests. I would like to point out that using fixtures in the above example would probably be overkill, but for more complex test data like checking hexadecimal values are valid then it would be a lot more useful.

Ameliorate answered 27/1, 2017 at 22:47 Comment(1)
Thank you very much for your answer. If I understand it right you use a fixtur in codeception like a fix (static) variable. And a stub for simulating an object. I think it is confusing because you often read that stubs are fixtures.Guerin

© 2022 - 2024 — McMap. All rights reserved.