diff --git a/app/Phabricator/ProjectsMap.php b/app/Phabricator/ProjectsMap.php
index aeaf39a..add5015 100644
--- a/app/Phabricator/ProjectsMap.php
+++ b/app/Phabricator/ProjectsMap.php
@@ -1,278 +1,278 @@
 <?php
 
 namespace Nasqueron\Notifications\Phabricator;
 
-use Nasqueron\Notifications\Phabricator\PhabricatorAPIClient as ApiClient;
+use Nasqueron\Notifications\Contracts\APIClient as APIClient;
 
 use App;
 use Cache;
 
 class ProjectsMap implements \IteratorAggregate, \ArrayAccess {
 
     ///
     /// Private properties and constants
     ///
 
     /**
      * The maximum number of projects to fetch
      */
     const LIMIT = 1000;
 
     /**
      * The projects as an array with phid as keys, project names as $value
      *
      * @var string[]
      */
     private $map = [];
 
     /**
      * The Phabricator instance name for this projects map
      *
      * @var string
      */
     private $instanceName;
 
     /**
      *
      * @var Nasqueron\Notifications\Contracts\APIClient
      */
     private $apiClient;
 
     /**
     * The source of the map
     *
     * @var string
     */
     private $source = 'unloaded';
 
     ///
     /// Constructor
     ///
 
     /**
      * Initializes a new instance of ProjectsMap.
      *
      * @param string $instanceName The Phabricator instance name
      */
     public function __construct ($instanceName) {
         $this->instanceName = $instanceName;
     }
 
     ///
     /// IteratorAggregate interface implementation
     ///
 
     /**
      * Gets iterator.
      *
      * @return Traversable
      */
     public function getIterator () {
         return new \ArrayIterator($this->map);
     }
 
     ///
     /// ArrayAccess interface implementation
     ///
 
     /**
      * Determines whether an offset exists.
      *
      * @param mixed $offset The offset
      * @return bool
      */
     public function offsetExists ($offset) {
         return array_key_exists($offset, $this->map);
     }
 
     /**
      * Gets the value at the specified offset.
      *
      * @param mixed $offset The offset.
      * @return mixed The value
      */
     public function offsetGet ($offset) {
         return $this->map[$offset];
     }
 
     /**
      * Assigns a value to the specified offset.
      *
      * @param mixed $offset The offset
      * @param mixed $value The value to assign
      */
     public function offsetSet ($offset, $value) {
         $this->map[$offset] = $value;
     }
 
     /**
      * Unsets a value at the specified offset.
      *
      * @param mixed $offset The offset where to remove the value
      */
     public function offsetUnset ($offset) {
         unset($this->map[$offset]);
     }
 
     ///
     /// Static constructors
     ///
 
     /**
      * Gets a new ProjectsMap instance from cache or API when not cached.
      *
      * @param string $phabricatorInstanceName The Phabricator instance name
      * @return ProjectsMap
      */
     public static function load ($phabricatorInstanceName) {
         $instance = new self($phabricatorInstanceName);
 
         if ($instance->isCached()) {
             $instance->loadFromCache();
         } else {
             $instance->fetchFromAPI();
         }
 
         return $instance;
     }
 
     /**
      * Gets a new ProjectsMap instance and queries Phabricator API to fill it.
      *
      * @param string $phabricatorInstanceName The Phabricator instance name
      * @param Nasqueron\Notifications\Contracts\APIClient $apiClient The Phabricator API client
      * @return ProjectsMap
      */
-    public static function fetch ($phabricatorInstanceName, APIClient $apiClient = null) {
+    public static function fetch ($phabricatorInstanceName, ?APIClient $apiClient = null) {
         $instance = new self($phabricatorInstanceName);
         $instance->setAPIClient($apiClient);
         $instance->fetchFromAPI();
         return $instance;
     }
 
     ///
     /// API
     ///
 
     /**
      * @return Nasqueron\Notifications\Contracts\APIClient
      */
     public function getAPIClient () {
         if ($this->apiClient === null) {
             $factory = App::make('phabricator-api');
             $this->apiClient = $factory->getForProject($this->instanceName);
         }
         return $this->apiClient;
     }
 
     /**
      * @param Nasqueron\Notifications\Contracts\APIClient $apiClient
      */
-    public function setAPIClient (APIClient $apiClient = null) {
+    public function setAPIClient (?APIClient $apiClient = null) {
         $this->apiClient = $apiClient;
     }
 
     /**
      * Fetches the projects' map from the Phabricator API.
      *
      * @throws \Exception when API reply is empty or invalid.
      */
     private function fetchFromAPI () {
         $reply = $this->getAPIClient()->call(
             'project.query',
             [ 'limit' => self::LIMIT ]
         );
 
         if (!$reply) {
             throw new \Exception("Empty reply calling project.query at $this->instanceName Conduit API.");
         }
 
         if (!property_exists($reply, 'data')) {
             throw new \Exception("Invalid reply calling project.query at $this->instanceName Conduit API.");
         }
 
         foreach ($reply->data as $phid => $projectInfo) {
             $this->offsetSet($phid, $projectInfo->name);
         }
 
         $this->source = 'api';
     }
 
     ///
     /// Cache
     ///
 
     /**
      * Gets cache key.
      *
      * @return string The cache key for the current projects map
      */
     private function getCacheKey () {
         return class_basename(get_class($this)) . '-' . md5($this->instanceName);
     }
 
     /**
      * Determines if the instance is cached
      *
      * @return bool true if cached; otherwise, false.
      */
     public function isCached () {
         return Cache::has($this->getCacheKey());
     }
 
     /**
      * Saves data to cache
      */
     public function saveToCache () {
         Cache::forever($this->getCacheKey(), $this->map);
     }
 
     /**
      * Loads data from cache
      *
      * Populates 'map' and 'source' properties
      */
     public function loadFromCache () {
         $cachedMap = Cache::get($this->getCacheKey());
         if ($cachedMap !== null) {
             $this->map = $cachedMap;
             $this->source = 'cache';
         }
     }
 
     ///
     /// Output
     ///
 
     /**
      * Gets project name, refreshing the cache if needed.
      *
      * @param string $projectPHID the PHID of the project to query the name
      * @return string The name of the poject, or an empty string if not found
      */
     public function getProjectName ($projectPHID) {
         if ($this->offsetExists($projectPHID)) {
             return $this->offsetGet($projectPHID);
         }
 
         if ($this->source !== 'api') {
             $this->fetchFromAPI();
             return $this->getProjectName($projectPHID);
         }
 
         return "";
     }
 
     /**
      * Returns the projects map as an array.
      *
      * @return array An array, each row containing ['PHID', 'project name']
      */
     public function toArray () {
         $array = [];
         foreach ($this->map as $phid => $projectName) {
             $array[] = [$phid, $projectName];
         }
         return $array;
     }
 }
diff --git a/composer.json b/composer.json
index d58dfb3..a30893d 100644
--- a/composer.json
+++ b/composer.json
@@ -1,56 +1,56 @@
 {
   "name": "nasqueron/notifications",
   "description": "Nasqueron notifications center",
   "keywords": [
     "nasqueron",
     "activemq",
     "AMQP",
     "notifications"
   ],
   "license": "BSD-2-Clause",
   "type": "project",
   "require": {
-    "php": ">=5.6.0",
+    "php": ">=7.1.0",
     "laravel/framework": "5.2.*",
     "guzzlehttp/guzzle": "^6.2",
     "keruald/dockerhub": "^0.0.3",
     "keruald/github": "^0.2.0",
     "keruald/broker": "^0.4.1",
     "keruald/mailgun": "^0.0.1",
     "netresearch/jsonmapper": "~0.1.0",
     "sentry/sentry": "^0.13.0"
   },
   "require-dev": {
     "fzaninotto/faker": "~1.4",
     "mockery/mockery": "0.9.*",
     "phpmd/phpmd" : "@stable",
     "phpunit/phpunit": "~4.0",
     "phpspec/phpspec": "~2.1",
     "squizlabs/php_codesniffer": "2.*",
     "symfony/css-selector": "~3.0",
     "symfony/dom-crawler": "~3.0"
   },
   "autoload": {
     "psr-4": {
       "Nasqueron\\Notifications\\": "app/",
       "Nasqueron\\Notifications\\Tests\\": "tests/"
     }
   },
   "scripts": {
     "post-root-package-install": [
       "php -r \"copy('.env.example', '.env');\""
     ],
     "post-create-project-cmd": [
       "php artisan key:generate"
     ],
     "phpmd": [
       "vendor/bin/phpmd app/ xml ruleset.xml"
     ],
     "test": [
       "phpunit --no-coverage"
     ]
   },
   "config": {
     "preferred-install": "dist"
   }
 }
diff --git a/tests/Phabricator/ProjectsMapTest.php b/tests/Phabricator/ProjectsMapTest.php
index dd2e5b2..273e6e2 100644
--- a/tests/Phabricator/ProjectsMapTest.php
+++ b/tests/Phabricator/ProjectsMapTest.php
@@ -1,192 +1,203 @@
 <?php
 
 namespace Nasqueron\Notifications\Tests\Phabricator;
 
+use Nasqueron\Notifications\Contracts\APIClient;
 use Nasqueron\Notifications\Phabricator\ProjectsMap;
 use Nasqueron\Notifications\Tests\TestCase;
 
 use Mockery;
 
 class ProjectsMapTest extends TestCase {
 
     /**
      * @var Nasqueron\Notifications\Phabricator\ProjectsMap
      */
     private $map;
 
     public function setUp () {
         parent::setUp();
 
         //
         // We mock the API, so an imaginary instance of Phabricator
         // will return 3 results: Accounts, Agora & architecture.
         //
         // Agora has the key "PHID-PROJ-cztcgpvqr6smnnekotq7".
         //
 
         $this->mockPhabricatorAPIForProjectsMap();
         $this->map = ProjectsMap::fetch("http://phabricator.acme.tld");
     }
 
     public function testIteratorIsTraversable () {
         $this->assertInstanceOf(
             "Traversable",
             $this->map->getIterator()
         );
     }
 
     ///
     /// Tests for ArrayAccess
     ///
 
     public function testOffsetExistsWhenItDoes () {
         $this->assertTrue(
             $this->map->offsetExists("PHID-PROJ-cztcgpvqr6smnnekotq7")
         );
     }
 
     public function testOffsetExistsWhenItDoesNot () {
         $this->assertFalse(
             $this->map->offsetExists("non-existing-key")
         );
     }
 
     public function testOffsetGetWhenItDoesExist () {
         $this->assertSame(
             "Agora",
             $this->map->offsetGet("PHID-PROJ-cztcgpvqr6smnnekotq7")
         );
     }
 
     /**
      * @expectedException ErrorException
      */
     public function testOffsetGetWhenItDoesNotExist () {
         $this->map->offsetGet("non-existing-key");
     }
 
     /**
      * @covers Nasqueron\Notifications\Phabricator\ProjectsMap::offsetSet
      */
     public function testOffsetSet () {
         $this->map->offsetSet("newkey", "quux");
         $this->assertSame("quux", $this->map->offsetGet("newkey"));
     }
 
     /**
      * @covers Nasqueron\Notifications\Phabricator\ProjectsMap::offsetUnset
      */
     public function testOffsetUnset () {
         unset($this->map["PHID-PROJ-cztcgpvqr6smnnekotq7"]);
         $this->assertFalse(
             $this->map->offsetExists("PHID-PROJ-cztcgpvqr6smnnekotq7")
         );
     }
 
     ///
     /// Tests for cache
     ///
 
     public function testCache () {
         $this->assertFalse($this->map->isCached());
         $this->map->saveToCache();
         $this->assertTrue($this->map->isCached());
     }
 
     public function testLoadFromCache () {
         $this->map->saveToCache();
 
         $map = new ProjectsMap("http://phabricator.acme.tld");
         $map->loadFromCache();
 
         $this->assertTrue(
             $map->offsetExists("PHID-PROJ-cztcgpvqr6smnnekotq7")
         );
     }
 
     public function testLoadWhenInCache () {
         $this->map->saveToCache();
 
         $map = ProjectsMap::load("http://phabricator.acme.tld");
         $this->assertTrue(
             $map->offsetExists("PHID-PROJ-cztcgpvqr6smnnekotq7")
         );
     }
 
     ///
     /// Tests for helper methods
     ///
 
     public function testGetProjectName () {
         $this->assertSame(
             "Agora",
             $this->map->getProjectName("PHID-PROJ-cztcgpvqr6smnnekotq7")
         );
     }
 
     public function testGetProjectNameForNewInstance () {
         $map = new ProjectsMap("http://phabricator.acme.tld");
         $this->assertSame(
             "Agora",
             $map->getProjectName("PHID-PROJ-cztcgpvqr6smnnekotq7")
         );
     }
 
     public function testGetProjectNameWhenItDoesNotExist () {
         $this->assertSame(
             "",
             $this->map->getProjectName("non-existing-key")
         );
     }
 
     public function testToArrayProducesArray () {
         $array = $this->map->toArray();
         $this->assertTrue(
             is_array($array),
             "Test if toArray return an array"
         );
     }
 
     public function testThatArrayCount () {
         $array = $this->map->toArray();
         $this->assertSame(3, count($array));
     }
 
     public function testThatArrayContainsExpectedData () {
         $this->assertSame(
             [
                  ["PHID-PROJ-6dg6ogx5pjmk24ur4tp4", "Accounts"],
                  ["PHID-PROJ-cztcgpvqr6smnnekotq7", "Agora"],
                  ["PHID-PROJ-3iew3cqf3htpazfyzb5a", "architecture"]
             ],
             $this->map->toArray()
         );
     }
 
     ///
     /// Tests API
     ///
 
-    private function mockPhabricatorAPIWithReply ($reply) {
-        return Mockery::mock('Nasqueron\Notifications\Contract\APIClient')
-            ->shouldReceive('call')
-            ->andReturn($reply);
+    private function mockPhabricatorAPIWithReply ($reply) : APIClient {
+        return (new class($reply) implements APIClient {
+            private $reply;
+
+            public function __construct ($reply) {
+                $this->reply = $reply;
+            }
+
+            public function setEndPoint ($url) : void { }
+
+            public function call ($method, $arguments = []) {
+                return $this->reply;
+            }
+        });
     }
 
     /**
      * @expectedException Exception
      */
     public function testFetchFromAPIWithoutReply () {
         $mock = $this->mockPhabricatorAPIWithReply(false);
         ProjectsMap::fetch("http://phabricator.acme.tld", $mock);
     }
 
     /**
      * @expectedException Exception
      */
     public function testFetchFromAPIInvalidReply () {
         $mock = $this->mockPhabricatorAPIWithReply(new \stdClass);
         ProjectsMap::fetch("http://phabricator.acme.tld", $mock);
     }
 
 }