Part 1: Testing Model Relationships in Laravel — Schema Tests
Tags: phpunit, laravel, codequality, unittesting
Published: 2019-10-08 11:51:24

---
title: Part 1: Testing Model Relationships in Laravel — Schema Tests
published: true
tags: phpunit,laravel,code-quality,unit-testing
canonical_url: 
---

### Part 1: Testing Model Relationships in Laravel — Schema Tests

![](https://cdn-images-1.medium.com/max/1024/1*VKkxNdeOKPu2SDklt6cs1w.png)<figcaption>Laravel Database Designer — <a href="https://biodesign.cc/2015/03/10/laravel-database-designer/">Biodesign.cc</a></figcaption>

**Laravel makes TDD a lot more fun, it is such a joy to work with .** The essence of the tests in this series is to ensure that your app model relationship is not missing a bolt. The code snippets will be available for easy reach at this [**_Github project link_**](https://github.com/tonyfrenzy/laravel-model-relationship-tests).

### Table of contents

To make this post more organized it will be split into three (3) parts.

- Part 1: **Intro and Schema Tests**  ⏯
- Part 2: [**Testing Basic Model Relationships**](https://dev.to/tonyfrenzy/part-2-testing-model-relationships-in-laravel-basic-3a44)
- Part 3: [**Testing Polymorphic Relationships**](https://dev.to/tonyfrenzy/part-3-testing-model-relationships-in-laravel-polymorphic-m51)

Writing tests make your code rock solid, predictable and highly maintainable. I have written some terrible apps in the past and it can be unnerving when broken codes scream **in — y o u r — face**. Those years I had no clue about unit tests — fix one bug and another one surfaces, more annoying is that you don’t know when another will pop up. Errors are bound to occur if relevant models are missing or wrongly connected.

### Unit and Feature Tests

**Unit Tests** are written for small pieces of a code base such as methods or attributes in a class. It usually deals with testing fine details at low level only. In our case we will be testing some methods on Laravel model classes, that is, model connections and relationships between different parts of an app.

**Feature Tests** is more encompassing as it sums up different part of a code and tests how well they inter-operate eg functional tests and integration tests on components, modules etc. We are not going into functional test in this post.

**NB:** _it is assumed that you have a working knowledge of Laravel, therefore nitty gritty of_ [_installation_](https://laravel.com/docs/6.x/installation)_,_ [_eloquent model_](https://laravel.com/docs/6.x/eloquent) _setup and_ [_relationship_](https://laravel.com/docs/6.x/eloquent-relationships) _are not discussed. However, test relevant topics will be discussed in depth._

**To** [**install a new laravel app**](https://laravel.com/docs/6.x/installation) **:**

- `laravel new modelRelTests` via **_installer_**
- `composer create-project --prefer-dist laravel/laravel modelRelTests` via **_create-project_**

### 1. Set Up Test Suite

We are going to make use of an sqlite database and use it in memory for faster test runs. Go to phpunit.xml at the root directory of your application and add:

```
...
<server name=" **DB\_CONNECTION**" value=" **sqlite**"/>
<server name=" **DB\_DATABASE**" value=" **:memory:**"/>
```

### 2. Creating a Test Class

If we run `vendor/bin/phpunit` at this point we get 2 tests for the dummy tests added by Laravel, one test each in the Unit and Feature test directories. Seeing the green is refreshing. You should delete the two files in preparation for our real tests.

By default, every new Laravel installation comes with a **User model** class (along with migration, controller etc) but not a test. We should create our own test file with the command:

`php artisan make:test **UserTest --unit**`

This creates a test file named **UserTest.php** within the **_tests/Unit_** directory in the root folder. The `--unit flag` implies that we are creating a unit test and should add the generated file to the unit test directory. Without the `--unit flag` we have a feature test and it gets added to **_tests/Feature_** directory.

### 3. Schema Test — My First Test in Every Model

Before visiting model relationship tests, my very first unit test in every Laravel model is the **schema test**. We can use this test to ensure that relevant table columns are not missing and also have the correct and expected **names**. All we need to do is this:

{% gist https://gist.github.com/tonyfrenzy/ddabba2e7cc8c8a12f369136da5414e5 %}

Take note of :

- `use Illuminate\Support\Facades\Schema;` namespace.
- `RefreshDatabase` and `WithFaker` traits. These two traits are important in most tests since you will most likely need a database of data to test your models and the faker library to populate a database with data to be tested upon.

If you want to be explicit about your schema checks you may check each individual field with:

- `...Schema:: **hasColumn** ('model', **'column'** ), 1);` instead of
- `...Schema:: **hasColumns** ('model', **['column\_1', 'column\_2']**), 1);` which checks all columns existence at once.

I prefer `**hasColumns()**` though, odd part is that you get a general error report and so don’t know the actual column affected unless you check thoroughly.

Run `vendor/bin/phpunit` and see the result below 👇

![](https://cdn-images-1.medium.com/max/1024/1*6sI2CZSLfC4z1dMb9oLR-A.png)<figcaption>TDD — failed because database is not set</figcaption>

**_This test failed, why?_** We have not set up or created our database yet. Set up your database configurations within the `.env` file according to your machine. See the snippet below:

```
DB\_DATABASE=homestead
DB\_USERNAME=homestead
DB\_PASSWORD=secret
```

Then, create your database within your xampp, wamp or homestead and run:

`$ php artisan migrate`

**Illuminate\Database\QueryException : SQLSTATE[42000]:** If you encounter the `Illuminate\Database\QueryException : SQLSTATE[42000]` error while running the migration like in image below

![](https://cdn-images-1.medium.com/max/1024/1*4r6s2xdY_8Pg6bvPJLmOVA.png)<figcaption>Illuminate\Database\QueryException</figcaption>

Go to **App/Providers/AppServiceProvider.php** and make the following updates. Within the boot method add `Schema::defaultStringLength(191);` and add a the namespace like so `use Illuminate\Support\Facades\Schema;`. See below 👇

![](https://cdn-images-1.medium.com/max/429/1*CRkxE3dLl6g0pgtxf9kUpA.png)<figcaption>Fix Illuminate\Database\QueryException : SQLSTATE[42000] error.</figcaption>

Run `vendor/bin/phpunit` again and you should get a success result as below:

![](https://cdn-images-1.medium.com/max/1024/1*xNAzBdtHRKL1xf1KlQOEcA.png)<figcaption>Test Result Successful!</figcaption>

Play around a little more by adding a **_new column_** into the test, do not add to the schema migration file initially, run the test to see results, failed? Make it pass. This particular test may look boring but from the ground up you can be sure your schema integrity is accounted for.

### **4. Creating Aliases for Your CLI Commands**

Now that you are beginning to write tests there will be a lot of tests to run. It would make much sense to have shortcut form of some lengthy commands, the cli commands you use often. This will surely improve your productivity. [**Bash alias** es](https://opensource.com/article/19/7/bash-aliases) to the rescue, it is a method of supplementing or overriding **Bash** commands with new ones eg allow users to customize their experience in a POSIX terminal.

- `alias name="command to shorten"` ** — creates a new alias ‘name’** NB: there are no spaces around the `=` sign.
- `alias` ** — displays all your set aliases** directly in the CLI.
- On a Windows PC, you may access and manage a list of your set aliases in the  **_.bash\_profile_** file at `C:\Users\yourUsername\.bash\_profile`. Here you can add, update or remove the entries.

I use the commands below most times in my tests:

- **_pu_** `vendor/bin/phpunit` this runs all tests within the tests directory.
- **_puf_** `vendor/bin/phpunit --filter` <pattern> this selectively runs test within all files and test methods whose name has the string (pattern).
- **_putu_** `vendor/bin/phpunit --testsuite Unit` this runs all tests within the Test\Units directory only.
- **_putf_** `vendor/bin/phpunit --testsuite Feature` this runs all tests within the `Test\Features` directory only.

There are more others but these ones comes handy for me all the time.

### Conclusion

I become paranoid if I write an app without some tests these days. I learnt the hard way and has since inculcate the habit of writing comprehensive tests for my apps _— the predictability, ease of maintenance and confidence that accompanies a well tested codebase is indescribable._ Kindly check the remaining two parts (see links below 👇) for they are the biggest deal.

- ⏯Part 1: **Intro and Schema Tests**
- 👉Part 2: [**Testing Basic Model Relationships**](https://dev.to/tonyfrenzy/part-2-testing-model-relationships-in-laravel-basic-3a44)
- 👉Part 3: [**Testing Polymorphic Relationships**](https://dev.to/tonyfrenzy/part-3-testing-model-relationships-in-laravel-polymorphic-m51)

Your comments are highly appreciated.