# Spies

Spies let you spy on a function or class method when it is called indirectly by some other code. It also allows you to change its behavior, if needed. You can spy a function or class method by using the \Verde\spyOn helper method.

NOTE: Spies require runkit7 to work!

# Syntax

both methods below return a mock function

# Spy on a function:

$spy = spyOn(functionName)

# Spy on a class method:

$spy = spyOn(className, classMethod)

# Example

Suppose you want to make a pizza, and so your function needs to retrieve the list of ingredients before baking everything.

<?php

function getPizzaIngredients(string $name)
{
    $content = file_get_contents('http://example.com/api/v1/get-ingredients/?name=' . $name);

    return json_decode($content, TRUE); 
}

function bakePizza(array $ingredients)
{
    // here where the cooking happens :)
}

function makePizza(string $name)
{
    $ingredients = getPizzaIngredients($name);

    bakePizza($ingredients);
}

In this case you want make sure that getPizzaIngredients gets called first, and after bakePizza, so the test will looks like:

<?php

use function Verde\expect;
use function Verde\spyOn;

test('retrieves the ingredient first and then bake the pizza', function () {
    $spyGetPizzaIngredients = spyOn('getPizzaIngredients');
    $spyBakePizza = spyOn('bakePizza');
    
    // We don't want to make the HTTP request
    $spyGetPizzaIngredients->mockReturnValue(['Mozzarella', 'Pomodoro']);

    makePizza('Margherita');

    // Here we make sure that the functions are called in the right order
    expect($spyGetPizzaIngredients)->toHaveBeenCalledBefore($spyBakePizza);
    
    // We can also check the arguments passed
    expect($spyGetPizzaIngredients)->toHaveBeenCalledWith('Margherita');
    expect($spyBakePizza)->toHaveBeenCalledWith(['Mozzarella', 'Pomodoro']);
});