Data Providers in PHPUnit
Tags: php, laravel
Published: 2022-04-02 04:00:52

---
title: Data Providers in PHPUnit
published: true
date: 2022-03-30 12:53:47 UTC
tags: php,laravel
canonical_url: https://adithya.dev/data-providers-in-phpunit/
---

When I built a [Salary Calculator for Germany](https://www.arbeitnow.com/tools/salary-calculator/germany) using Laravel, I started covering the code with Unit Tests using PHPUnit. This particularly came in handy when I had to cover more edge cases as I was able to trust the calculation. One of the features that I didn't know until that point was [Data Providers in PHPUnit](https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html#data-providers).

### What is a Data Provider?

When I write a test for a method, or a class, I write multiple assertions with the values for the same code. Data Providers are useful here when all that changes is the values passed to the method.

> DataProviders are a framework for easily controlling how data can be provided from a source

Let's take an example of how you would write a test **without** data providers. Assume you have a method `add($a, $b)` in a class `Operations` that returns a value, summing up the numbers.

```
    public function test_add()
    {
    	$actual = (new Operations)->add(1, 2);
        $this->assertEquals(3, $actual);
    }

```

When you want to add multiple assertions, you would be tempted to add another assertion like this:

```
    public function test_add()
    {
    	$actual = (new Operations)->add(1, 2);
        $this->assertEquals(3, $actual);
        
        $actual = (new Operations)->add(3, 4);
        $this->assertEquals(7, $actual);
    }
    
    // Or a test per method
    public function test_add_first()
    {
    	$actual = (new Operations)->add(1, 2);
        $this->assertEquals(3, $actual);
    }
    
    public function test_add_second()
    {
    	$actual = (new Operations)->add(3, 4);
        $this->assertEquals(7, $actual);
    }

    

```

These add overhead if the signature of the method changes, or when you want to cover more cases.

### How to use a Data Provider in PHPUnit

A Data Provider can simplify this, allowing you to pass multiple sets of values for the same test. From the official documentation:

<!--kg-card-begin: markdown-->

A data provider method

- must be `public `
- and either return an array of arrays or an object that implements the `Iterator` interface and yields an array for each iteration step.
<!--kg-card-end: markdown-->

Let's convert the existing test case using a Data Provider. We will use a `dataProvider` annotation following the name of the data provider.

```
/**
* @dataProvider addProvider
*/
public function test_add($a, $b, $expected)
{
	$actual = (new Operations)->add($a, $b);
    	$this->assertEquals($expected, $actual);
}

public function addProvider()
{
 	return array(
        	array(1, 2, 3),
        	array(4, 5, 7),
    );
}

```

In this case, PHPUnit would pass the take the array, loop through the items (array again) and pass the arguments based on the **position** of the method parameters.

For the first item, it will take `array(1, 2, 3)`, call `test_add(1, 2, 3)`  and validate the assertions. Then the next item and so on.

### Inline Data Providers in PHPUnit

In the test cases above with a Data Provider, we can simplify it even further by inlining the data provider. The annotation to use is `testWith`

<!--kg-card-begin: markdown-->
```
/**
* @testWith array(
        	array(1, 2, 3),
        	array(4, 5, 7),
    );
*/
public function test_add($a, $b, $expected)
{
	$actual = (new Operations)->add($a, $b);
    	$this->assertEquals($expected, $actual);
}

```
<!--kg-card-end: markdown-->