diff --git a/app/routes.php b/app/routes.php
index 186616bcf870e882c0f4ba782bd9c5598ee0abf9..ae0f4bc7f6ea37e5ab4a91c466627e5d3d132ba4 100644
--- a/app/routes.php
+++ b/app/routes.php
@@ -47,7 +47,7 @@ $app->group('', function (RouteCollectorProxy $group) {
         '/dataset/{name}/attribute/{id}/distinct',
         App\Action\AttributeDistinctAction::class
     );
-})->add(new App\Middleware\AdminMiddleware());
+})->add(new App\Middleware\AdminMiddleware($container->get(SETTINGS)['token']));
 
 $app->get('/search/{dname}', App\Action\SearchAction::class);
 $app->get('/download-file/{dname}/[{fpath:.*}]', App\Action\DownloadFileAction::class);
diff --git a/app/settings.php b/app/settings.php
index 711f051ff0e54b9e795006aab93075226c2f7112..7f55c640a8acc197ae086f47ac32a39effbf7ab4 100644
--- a/app/settings.php
+++ b/app/settings.php
@@ -31,7 +31,9 @@ return [
         'level' => getenv('LOGGER_LEVEL')
     ],
     'token' => [
-        'issuer' => getenv('TOKEN_ISSUER'),
-        'public_key_file' => getenv('TOKEN_PUBLIC_KEY_FILE')
+        //'issuer' => getenv('TOKEN_ISSUER'),
+        'enabled' => getenv('TOKEN_ENABLED'),
+        'public_key_file' => getenv('TOKEN_PUBLIC_KEY_FILE'),
+        'admin_role' => getenv('TOKEN_ADMIN_ROLE')
     ]
 ];
diff --git a/docker-compose.yml b/docker-compose.yml
index 1ac6ee621ccdb3981c2fc32edfb2ab04f8bb73bc..6d5d9d992cfd28023ed159ed0dc34dd21fc9d119 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -17,8 +17,9 @@ services:
             LOGGER_NAME: "anis-metamodel"
             LOGGER_PATH: "php://stderr"
             LOGGER_LEVEL: "debug"
-            TOKEN_ISSUER: http://localhost:8180/auth/realms/anis
+            TOKEN_ENABLED: 1
             TOKEN_PUBLIC_KEY_FILE: /data/public_key
+            TOKEN_ADMIN_ROLE: anis_admin
         ports:
             - 8080:80
         volumes:
diff --git a/doctrine-proxy/__CG__AppEntityDataset.php b/doctrine-proxy/__CG__AppEntityDataset.php
index f4530d3c63764deb8261217be725c9ac17f46773..49df6da3284f430e60ec08fe908580cd49932067 100644
--- a/doctrine-proxy/__CG__AppEntityDataset.php
+++ b/doctrine-proxy/__CG__AppEntityDataset.php
@@ -64,10 +64,10 @@ class Dataset extends \App\Entity\Dataset implements \Doctrine\ORM\Proxy\Proxy
     public function __sleep()
     {
         if ($this->__isInitialized__) {
-            return ['__isInitialized__', 'name', 'tableRef', 'label', 'description', 'display', 'count', 'vo', 'dataPath', 'selectableRow', 'project', 'datasetFamily', 'attributes'];
+            return ['__isInitialized__', 'name', 'tableRef', 'label', 'description', 'display', 'count', 'vo', 'dataPath', 'config', 'public', 'project', 'datasetFamily', 'attributes'];
         }
 
-        return ['__isInitialized__', 'name', 'tableRef', 'label', 'description', 'display', 'count', 'vo', 'dataPath', 'selectableRow', 'project', 'datasetFamily', 'attributes'];
+        return ['__isInitialized__', 'name', 'tableRef', 'label', 'description', 'display', 'count', 'vo', 'dataPath', 'config', 'public', 'project', 'datasetFamily', 'attributes'];
     }
 
     /**
@@ -345,23 +345,45 @@ class Dataset extends \App\Entity\Dataset implements \Doctrine\ORM\Proxy\Proxy
     /**
      * {@inheritDoc}
      */
-    public function getSelectableRow()
+    public function getConfig()
     {
 
-        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSelectableRow', []);
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getConfig', []);
 
-        return parent::getSelectableRow();
+        return parent::getConfig();
     }
 
     /**
      * {@inheritDoc}
      */
-    public function setSelectableRow($selectableRow)
+    public function setConfig($config)
     {
 
-        $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSelectableRow', [$selectableRow]);
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'setConfig', [$config]);
 
-        return parent::setSelectableRow($selectableRow);
+        return parent::setConfig($config);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getPublic()
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getPublic', []);
+
+        return parent::getPublic();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function setPublic($public)
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'setPublic', [$public]);
+
+        return parent::setPublic($public);
     }
 
     /**
diff --git a/doctrine-proxy/__CG__AppEntityGroup.php b/doctrine-proxy/__CG__AppEntityGroup.php
index d0cefd24106b2d1571627907be881e1553db5686..ffd63b0ecf3875039dc5aeaf26b4aee616b3768a 100644
--- a/doctrine-proxy/__CG__AppEntityGroup.php
+++ b/doctrine-proxy/__CG__AppEntityGroup.php
@@ -64,10 +64,10 @@ class Group extends \App\Entity\Group implements \Doctrine\ORM\Proxy\Proxy
     public function __sleep()
     {
         if ($this->__isInitialized__) {
-            return ['__isInitialized__', 'id', 'label', 'datasetPrivileges'];
+            return ['__isInitialized__', 'id', 'label', 'datasets'];
         }
 
-        return ['__isInitialized__', 'id', 'label', 'datasetPrivileges'];
+        return ['__isInitialized__', 'id', 'label', 'datasets'];
     }
 
     /**
@@ -213,12 +213,23 @@ class Group extends \App\Entity\Group implements \Doctrine\ORM\Proxy\Proxy
     /**
      * {@inheritDoc}
      */
-    public function getDatasetPrivileges()
+    public function getDatasets()
     {
 
-        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDatasetPrivileges', []);
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDatasets', []);
 
-        return parent::getDatasetPrivileges();
+        return parent::getDatasets();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function setDatasets($datasets)
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDatasets', [$datasets]);
+
+        return parent::setDatasets($datasets);
     }
 
     /**
diff --git a/doctrine-proxy/__CG__AppEntityInstance.php b/doctrine-proxy/__CG__AppEntityInstance.php
index 6d4e85d0a5729942088be87a8e9fb91af4d8abf9..9e0937f12f6a03a6d8e541a6b7417f927835df37 100644
--- a/doctrine-proxy/__CG__AppEntityInstance.php
+++ b/doctrine-proxy/__CG__AppEntityInstance.php
@@ -64,10 +64,10 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy
     public function __sleep()
     {
         if ($this->__isInitialized__) {
-            return ['__isInitialized__', 'name', 'label', 'clientUrl', 'datasetFamilies'];
+            return ['__isInitialized__', 'name', 'label', 'clientUrl', 'config', 'datasetFamilies'];
         }
 
-        return ['__isInitialized__', 'name', 'label', 'clientUrl', 'datasetFamilies'];
+        return ['__isInitialized__', 'name', 'label', 'clientUrl', 'config', 'datasetFamilies'];
     }
 
     /**
@@ -232,6 +232,28 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy
         return parent::setClientUrl($clientUrl);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function getConfig()
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'getConfig', []);
+
+        return parent::getConfig();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function setConfig($config)
+    {
+
+        $this->__initializer__ && $this->__initializer__->__invoke($this, 'setConfig', [$config]);
+
+        return parent::setConfig($config);
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/src/Action/GroupListAction.php b/src/Action/GroupListAction.php
index 84bf07b968a9594bb58ebc4c796ff1eaaaa6c08c..b95832ef66fa8ddbd1eacde55dfd4ac2314b6106 100644
--- a/src/Action/GroupListAction.php
+++ b/src/Action/GroupListAction.php
@@ -45,7 +45,7 @@ final class GroupListAction extends AbstractAction
             $parsedBody = $request->getParsedBody();
 
             // To work this action needs group information
-            foreach (array('label') as $a) {
+            foreach (array('label', 'datasets') as $a) {
                 if ($this->isEmptyField($a, $parsedBody)) {
                     throw new HttpBadRequestException(
                         $request,
@@ -70,10 +70,9 @@ final class GroupListAction extends AbstractAction
      */
     private function postGroup(array $parsedBody): Group
     {
-        $group = new Group(
-            $this->getDatasets($parsedBody['datasets'])
-        );
+        $group = new Group();
         $group->setLabel($parsedBody['label']);
+        $group->setDatasets($this->getDatasets($parsedBody['datasets']));
 
         $this->em->persist($group);
         $this->em->flush();
diff --git a/src/Entity/Group.php b/src/Entity/Group.php
index 161ef31ac79cd72a4ff43f0d4a39d8b9ea0cc023..501d4e824e1ec91af40f390eefc38067607c6be0 100644
--- a/src/Entity/Group.php
+++ b/src/Entity/Group.php
@@ -12,9 +12,6 @@ declare(strict_types=1);
 
 namespace App\Entity;
 
-use Doctrine\Common\Collections\Collection;
-use Doctrine\Common\Collections\ArrayCollection;
-
 /**
 * @Entity
 * @Table(name="anis_group")
@@ -49,11 +46,6 @@ class Group implements \JsonSerializable
      */
     protected $datasets;
 
-    public function __construct(array $datasets)
-    {
-        $this->datasets = new ArrayCollection($datasets);
-    }
-
     public function getId()
     {
         return $this->id;
diff --git a/src/Middleware/AdminMiddleware.php b/src/Middleware/AdminMiddleware.php
index f05395e22bc697a12674163dcf1243d237ef2a2a..cdcdc7ec68fa96ccf80e10af398ae28482a50482 100644
--- a/src/Middleware/AdminMiddleware.php
+++ b/src/Middleware/AdminMiddleware.php
@@ -20,20 +20,50 @@ use Nyholm\Psr7\Response as NyholmResponse;
 
 final class AdminMiddleware implements MiddlewareInterface
 {
+    /**
+     * Contains settings to handle Json Web Token
+     *
+     * @var array
+     */
+    private $settings;
+
+    /**
+     * Create the classe before call process to execute this middleware
+     *
+     * @param array $settings Settings about token
+     */
+    public function __construct(array $settings)
+    {
+        $this->settings = $settings;
+    }
+
     public function process(Request $request, RequestHandler $handler): Response
     {
-        if ($request->getMethod() === OPTIONS || $request->getMethod() === GET) {
+        if (
+            $request->getMethod() === OPTIONS
+            || $request->getMethod() === GET
+            || $this->settings['enabled'] === 0
+        ) {
             return $handler->handle($request);
         }
 
         $token = $request->getAttribute('token');
         if (!$token) {
-            return (new NyholmResponse())->withStatus(401);
+            return $this->getResponse('HTTP 401: This url need a valid token', 401);
         }
-        if (!in_array('anis_admin', $token->getClaim('realm_access')->roles)) {
-            return (new NyholmResponse())->withStatus(403);
+        if (!in_array($this->settings['admin_role'], $token->getClaim('realm_access')->roles)) {
+            return $this->getResponse('HTTP 403: This url need a higher level of permission', 403);
         }
 
         return $handler->handle($request);
     }
+
+    private function getResponse(string $message, int $code)
+    {
+        $resonse = new NyholmResponse();
+        $resonse->getBody()->write(json_encode(array(
+            'message' => $message
+        )));
+        return $resonse->withStatus($code);
+    }
 }
diff --git a/src/Middleware/AuthorizationMiddleware.php b/src/Middleware/AuthorizationMiddleware.php
index 53fe04320d88d60c984dae8921d38e1ab0a4ad12..8f660ef6d989a2af3b039f4eb220c7fe4528d5da 100644
--- a/src/Middleware/AuthorizationMiddleware.php
+++ b/src/Middleware/AuthorizationMiddleware.php
@@ -15,6 +15,7 @@ namespace App\Middleware;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
 use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
+use Slim\Exception\HttpUnauthorizedException;
 use Nyholm\Psr7\Response as NyholmResponse;
 use Psr\Http\Server\MiddlewareInterface;
 use Lcobucci\JWT\Parser;
@@ -58,7 +59,11 @@ final class AuthorizationMiddleware implements MiddlewareInterface
      */
     public function process(Request $request, RequestHandler $handler): Response
     {
-        if ($request->getMethod() === OPTIONS || !$request->hasHeader('Authorization')) {
+        if (
+            $request->getMethod() === OPTIONS
+            || !$request->hasHeader('Authorization')
+            || $this->settings['enabled'] === 0
+        ) {
             return $handler->handle($request);
         }
 
@@ -66,7 +71,9 @@ final class AuthorizationMiddleware implements MiddlewareInterface
         $bearer = $request->getHeader('Authorization');
         $data = explode(' ', $bearer[0]);
         if ($data[0] !== 'Bearer') {
-            return (new NyholmResponse())->withStatus(401);
+            return $this->getUnauthorizedResponse(
+                'HTTP 401: Authorization must contain a string with the following format -> Bearer JWT'
+            );
         }
 
         // Parse the JWT Token
@@ -74,18 +81,38 @@ final class AuthorizationMiddleware implements MiddlewareInterface
 
         // Validating token (verifying expiration date and issuer)
         $data = new ValidationData();
-        // TODO: Ajouter une config pour vérifier ou non le issuer
-        // $data->setIssuer($this->settings['issuer']);
         if (!$token->validate($data)) {
-            return (new NyholmResponse())->withStatus(401);
+            return $this->getUnauthorizedResponse('HTTP 401: Access Token is not valid or has expired');
         }
 
         // Test token signature with the public key
         $publicKey = new Key('file://' . $this->settings['public_key_file']);
         if (!$token->verify(new Sha256(), $publicKey)) {
-            return (new NyholmResponse())->withStatus(401);
+            return $this->getUnauthorizedResponse('HTTP 401: Access Token signature is not valid');
         }
 
         return $handler->handle($request->withAttribute('token', $token));
     }
+
+    // private function getPublicKey(string $issuer, string $kid): string
+    // {
+    //     $urlOpenIdConfiguration = $issuer . '/.well-known/openid-configuration';
+    //     $openIdConfiguration = json_decode(file_get_contents($urlOpenIdConfiguration), true);
+    //     $jwksUri = $openIdConfiguration['jwks_uri'];
+    //     $jwks = json_decode(file_get_contents($jwksUri), true);
+    //     foreach ($jwks['keys'] as $jwk) {
+    //         if ($jwk['kid'] === $kid) {
+    //             return $jwk['x5c'];
+    //         }
+    //     }
+    // }
+
+    private function getUnauthorizedResponse(string $message)
+    {
+        $resonse = new NyholmResponse();
+        $resonse->getBody()->write(json_encode(array(
+            'message' => $message
+        )));
+        return $resonse->withStatus(401);
+    }
 }
diff --git a/tests/Action/GroupActionTest.php b/tests/Action/GroupActionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..259ce6432725976dc1cad1a19ac186fc90340803
--- /dev/null
+++ b/tests/Action/GroupActionTest.php
@@ -0,0 +1,197 @@
+<?php
+
+/*
+ * This file is part of Anis Server.
+ *
+ * (c) Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+declare(strict_types=1);
+
+namespace App\Tests\Action;
+
+use PHPUnit\Framework\TestCase;
+use Nyholm\Psr7\ServerRequest;
+use Nyholm\Psr7\Response;
+use Slim\Exception\HttpNotFoundException;
+use Slim\Exception\HttpBadRequestException;
+use App\tests\EntityManagerBuilder;
+use App\Entity\Group;
+use App\Entity\Database;
+use App\Entity\Project;
+use App\Entity\Instance;
+use App\Entity\DatasetFamily;
+use App\Entity\Dataset;
+
+final class GroupActionTest extends TestCase
+{
+    private $action;
+    private $entityManager;
+
+    protected function setUp(): void
+    {
+        $this->entityManager = EntityManagerBuilder::getInstance();
+        $this->action = new \App\Action\GroupAction($this->entityManager);
+    }
+
+    public function testOptionsHttpMethod(): void
+    {
+        $request = $this->getRequest('OPTIONS');
+        $response = ($this->action)($request, new Response(), array());
+        $this->assertSame($response->getHeaderLine('Access-Control-Allow-Methods'), 'GET, PUT, DELETE, OPTIONS');
+    }
+
+    public function testGroupIsNotFound(): void
+    {
+        $this->expectException(HttpNotFoundException::class);
+        $this->expectExceptionMessage('Group with id 1 is not found');
+        $request = $this->getRequest('GET');
+        $response = ($this->action)($request, new Response(), array('id' => 1));
+        $this->assertEquals(404, (int) $response->getStatusCode());
+    }
+
+    public function testGetAGroupById(): void
+    {
+        $group = $this->addAGroup();
+        $request = $this->getRequest('GET');
+        $response = ($this->action)($request, new Response(), array('id' => 1));
+        $this->assertSame(json_encode($group), (string) $response->getBody());
+    }
+
+    public function testEditAGroupEmptyLabelField(): void
+    {
+        $this->addAGroup();
+        $this->expectException(HttpBadRequestException::class);
+        $this->expectExceptionMessage('Param label needed to edit the group');
+        $request = $this->getRequest('PUT')->withParsedBody(array());
+        $response = ($this->action)($request, new Response(), array('id' => 1));
+        $this->assertEquals(400, (int) $response->getStatusCode());
+    }
+
+    public function testEditAGroupWithoutDataset(): void
+    {
+        $fields = array(
+            'label' => 'New_label',
+            'datasets' => array()
+        );
+        $this->addAGroup();
+        $request = $this->getRequest('PUT')->withParsedBody($fields);
+        $response = ($this->action)($request, new Response(), array('id' => 1));
+        $this->assertSame(json_encode(array_merge(['id' => 1], $fields)), (string) $response->getBody());
+    }
+
+    public function testEditAGroupWithDataset(): void
+    {
+        $dataset = $this->addADataset();
+        $fields = array(
+            'label' => 'New_label',
+            'datasets' => array($dataset->getName())
+        );
+        $this->addAGroup();
+        $request = $this->getRequest('PUT')->withParsedBody($fields);
+        $response = ($this->action)($request, new Response(), array('id' => 1));
+        $this->assertSame(json_encode(array_merge(['id' => 1], $fields)), (string) $response->getBody());
+    }
+
+    public function testDeleteAGroup(): void
+    {
+        $this->addAGroup();
+        $request = $this->getRequest('DELETE');
+        $response = ($this->action)($request, new Response(), array('id' => 1));
+        $this->assertSame(
+            json_encode(array('message' => 'Group with id 1 is removed!')),
+            (string) $response->getBody()
+        );
+    }
+
+    protected function tearDown(): void
+    {
+        $this->entityManager->getConnection()->close();
+    }
+
+    private function getRequest(string $method): ServerRequest
+    {
+        return new ServerRequest($method, '/group/1', array(
+            'Content-Type' => 'application/json'
+        ));
+    }
+
+    private function addAGroup(): Group
+    {
+        $group = new Group();
+        $group->setLabel('Group1');
+        $group->setDatasets(array());
+        $this->entityManager->persist($group);
+        $this->entityManager->flush();
+        return $group;
+    }
+
+    private function addProject(): Project
+    {
+        $database = new Database();
+        $database->setLabel('Test1');
+        $database->setDbName('test1');
+        $database->setType('pgsql');
+        $database->setHost('db');
+        $database->setPort(5432);
+        $database->setLogin('test');
+        $database->setPassword('test');
+        $this->entityManager->persist($database);
+
+        $project = new Project('anis_project');
+        $project->setLabel('Test project');
+        $project->setDescription('Test description');
+        $project->setLink('http://test.com');
+        $project->setManager('User1');
+        $project->setDatabase($database);
+        $this->entityManager->persist($project);
+
+        $this->entityManager->flush();
+        return $project;
+    }
+
+    private function addInstance(): Instance
+    {
+        $instance = new Instance('aspic', 'Aspic');
+        $instance->setClientUrl('http://cesam.lam.fr/aspic');
+        $this->entityManager->persist($instance);
+        $this->entityManager->flush();
+        return $instance;
+    }
+
+    private function addDatasetFamily(): DatasetFamily
+    {
+        $instance = $this->addInstance();
+
+        $family = new DatasetFamily($instance);
+        $family->setLabel('Default dataset');
+        $family->setDisplay(10);
+        $this->entityManager->persist($family);
+
+        $this->entityManager->flush();
+        return $family;
+    }
+
+    private function addADataset(): Dataset
+    {
+        $project = $this->addProject();
+        $family = $this->addDatasetFamily();
+
+        $dataset = new Dataset('obs_cat');
+        $dataset->setTableRef('v_obs_cat');
+        $dataset->setLabel('Obscat label');
+        $dataset->setDescription('Obscat description');
+        $dataset->setDisplay(10);
+        $dataset->setCount(10000);
+        $dataset->setVo(false);
+        $dataset->setDataPath('/mnt/obs_cat');
+        $dataset->setPublic(true);
+        $dataset->setProject($project);
+        $dataset->setDatasetFamily($family);
+        $this->entityManager->persist($dataset);
+        $this->entityManager->flush();
+        return $dataset;
+    }
+}
diff --git a/tests/Action/GroupListActionTest.php b/tests/Action/GroupListActionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4058eb2ce69ab041b89bf5b7133e7cdad84a6e23
--- /dev/null
+++ b/tests/Action/GroupListActionTest.php
@@ -0,0 +1,190 @@
+<?php
+
+/*
+ * This file is part of Anis Server.
+ *
+ * (c) Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+declare(strict_types=1);
+
+namespace App\Tests\Action;
+
+use PHPUnit\Framework\TestCase;
+use Nyholm\Psr7\ServerRequest;
+use Nyholm\Psr7\Response;
+use Slim\Exception\HttpBadRequestException;
+use App\tests\EntityManagerBuilder;
+use App\Entity\Group;
+use App\Entity\Database;
+use App\Entity\Project;
+use App\Entity\Instance;
+use App\Entity\DatasetFamily;
+use App\Entity\Dataset;
+
+final class GroupListActionTest extends TestCase
+{
+    private $action;
+    private $entityManager;
+
+    protected function setUp(): void
+    {
+        $this->entityManager = EntityManagerBuilder::getInstance();
+        $this->action = new \App\Action\GroupListAction($this->entityManager);
+    }
+
+    public function testOptionsHttpMethod(): void
+    {
+        $request = $this->getRequest('OPTIONS');
+        $response = ($this->action)($request, new Response(), array());
+        $this->assertSame($response->getHeaderLine('Access-Control-Allow-Methods'), 'GET, POST, OPTIONS');
+    }
+
+    public function testGetAllGroups(): void
+    {
+        $groups = $this->addGroups();
+        $request = $this->getRequest('GET');
+        $response = ($this->action)($request, new Response(), array());
+        $this->assertSame(
+            json_encode($groups),
+            (string) $response->getBody()
+        );
+    }
+
+    public function testAddANewGroupEmptyLabelField(): void
+    {
+        $this->expectException(HttpBadRequestException::class);
+        $this->expectExceptionMessage('Param label needed to add a new group');
+        $request = $this->getRequest('POST')->withParsedBody(array());
+        $response = ($this->action)($request, new Response(), array());
+        $this->assertEquals(400, (int) $response->getStatusCode());
+    }
+
+    public function testAddANewGroupWithoutDataset(): void
+    {
+        $fields = array(
+            'label' => 'group1',
+            'datasets' => []
+        );
+        $request = $this->getRequest('POST')->withParsedBody($fields);
+        $response = ($this->action)($request, new Response(), array());
+        $this->assertSame(
+            json_encode(array_merge(['id' => 1], $fields)),
+            (string) $response->getBody()
+        );
+        $this->assertEquals(201, (int) $response->getStatusCode());
+    }
+
+    public function testAddANewGroupWithDataset(): void
+    {
+        $dataset = $this->addADataset();
+        $fields = array(
+            'label' => 'group1',
+            'datasets' => array($dataset->getName())
+        );
+        $request = $this->getRequest('POST')->withParsedBody($fields);
+        $response = ($this->action)($request, new Response(), array());
+        $this->assertSame(
+            json_encode(array_merge(['id' => 1], $fields)),
+            (string) $response->getBody()
+        );
+        $this->assertEquals(201, (int) $response->getStatusCode());
+    }
+
+    protected function tearDown(): void
+    {
+        $this->entityManager->getConnection()->close();
+    }
+
+    private function getRequest(string $method): ServerRequest
+    {
+        return new ServerRequest($method, '/group', array(
+            'Content-Type' => 'application/json'
+        ));
+    }
+
+    private function addGroups(): array
+    {
+        $group = new Group();
+        $group->setLabel('Group1');
+        $group->setDatasets(array());
+        $this->entityManager->persist($group);
+
+        $group2 = new Group();
+        $group2->setLabel('Group2');
+        $group2->setDatasets(array());
+        $this->entityManager->persist($group2);
+
+        $this->entityManager->flush();
+        return array($group, $group2);
+    }
+
+    private function addProject(): Project
+    {
+        $database = new Database();
+        $database->setLabel('Test1');
+        $database->setDbName('test1');
+        $database->setType('pgsql');
+        $database->setHost('db');
+        $database->setPort(5432);
+        $database->setLogin('test');
+        $database->setPassword('test');
+        $this->entityManager->persist($database);
+
+        $project = new Project('anis_project');
+        $project->setLabel('Test project');
+        $project->setDescription('Test description');
+        $project->setLink('http://test.com');
+        $project->setManager('User1');
+        $project->setDatabase($database);
+        $this->entityManager->persist($project);
+
+        $this->entityManager->flush();
+        return $project;
+    }
+
+    private function addInstance(): Instance
+    {
+        $instance = new Instance('aspic', 'Aspic');
+        $instance->setClientUrl('http://cesam.lam.fr/aspic');
+        $this->entityManager->persist($instance);
+        $this->entityManager->flush();
+        return $instance;
+    }
+
+    private function addDatasetFamily(): DatasetFamily
+    {
+        $instance = $this->addInstance();
+
+        $family = new DatasetFamily($instance);
+        $family->setLabel('Default dataset');
+        $family->setDisplay(10);
+        $this->entityManager->persist($family);
+
+        $this->entityManager->flush();
+        return $family;
+    }
+
+    private function addADataset(): Dataset
+    {
+        $project = $this->addProject();
+        $family = $this->addDatasetFamily();
+
+        $dataset = new Dataset('obs_cat');
+        $dataset->setTableRef('v_obs_cat');
+        $dataset->setLabel('Obscat label');
+        $dataset->setDescription('Obscat description');
+        $dataset->setDisplay(10);
+        $dataset->setCount(10000);
+        $dataset->setVo(false);
+        $dataset->setDataPath('/mnt/obs_cat');
+        $dataset->setPublic(true);
+        $dataset->setProject($project);
+        $dataset->setDatasetFamily($family);
+        $this->entityManager->persist($dataset);
+        $this->entityManager->flush();
+        return $dataset;
+    }
+}