diff --git a/docker-compose.yml b/docker-compose.yml
index 3cfa17557f6da51eae4fb2dce5036a338d46975e..ff23e61fc8f9ba00a175ce3211043d0d01616c55 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -87,7 +87,7 @@ services:
       - db-ghost:/var/lib/mysql
 
   es01:
-    image: elasticsearch:7.6.1
+    image: elasticsearch:7.16.2
     restart: unless-stopped
     environment:
       node.name: es01
diff --git a/package-lock.json b/package-lock.json
index c32dba743fa033561364730f0db3a6b29cb20137..298a88b87bfad2b2718fae75a3d1c5c8653415d4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4448,6 +4448,12 @@
       "integrity": "sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==",
       "dev": true
     },
+    "@golevelup/ts-jest": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@golevelup/ts-jest/-/ts-jest-0.3.2.tgz",
+      "integrity": "sha512-hv+j/vau2oj5CuhY1CrTs48Qu+ZVXpm/56OzKcL2KVN8+yc0ZIMbvTIld1wbrT1RrvAuwfDmUM2s3aSy7veuwg==",
+      "dev": true
+    },
     "@hutson/parse-repository-url": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz",
diff --git a/package.json b/package.json
index 7bcfb722c57763dc38d71e4e785d5e0630e1cbc5..f0e4364726efd5249b775edaf3301d778e37eb29 100644
--- a/package.json
+++ b/package.json
@@ -60,6 +60,7 @@
   },
   "devDependencies": {
     "@compodoc/compodoc": "^1.1.16",
+    "@golevelup/ts-jest": "^0.3.2",
     "@nestjs/cli": "^7.5.1",
     "@nestjs/schematics": "^7.1.3",
     "@nestjs/testing": "^7.5.1",
diff --git a/src/admin/admin.controller.ts b/src/admin/admin.controller.ts
index ad0a493f351f0a25a9b66e18930f632f3c9f4966..3fae73b8f3970e7786f21eba848bef4ca20db68a 100644
--- a/src/admin/admin.controller.ts
+++ b/src/admin/admin.controller.ts
@@ -183,6 +183,6 @@ export class AdminController {
   @Delete('newsletterSubscription/:email')
   @ApiParam({ name: 'email', type: String, required: true })
   public async unsubscribeUserFromNewsletter(@Param() params): Promise<NewsletterSubscription> {
-    return this.newsletterService.deleteOneEmail(params.email);
+    return this.newsletterService.newsletterUnsubscribe(params.email);
   }
 }
diff --git a/src/categories/services/categories-accompagnement.service.spec.ts b/src/categories/services/categories-accompagnement.service.spec.ts
index 2690850884d95e003009cd4395d8d7125889d03b..a889a46f2b6744ab3caed6d07a947a5c8f3399a2 100644
--- a/src/categories/services/categories-accompagnement.service.spec.ts
+++ b/src/categories/services/categories-accompagnement.service.spec.ts
@@ -1,11 +1,16 @@
 import { getModelToken } from '@nestjs/mongoose';
 import { Test, TestingModule } from '@nestjs/testing';
-import { CategoriesAccompagnement } from '../schemas/categoriesAccompagnement.schema';
+import { CreateCategoriesAccompagnement } from '../dto/create-categoriesAccompagnement.dto';
 import { CategoriesAccompagnementService } from './categories-accompagnement.service';
 
 describe('CategoriesAccompagnementService', () => {
   let service: CategoriesAccompagnementService;
 
+  const mockCategoriesAccompagnementModel = {
+    create: jest.fn(),
+    find: jest.fn(),
+  };
+
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       imports: [],
@@ -13,7 +18,7 @@ describe('CategoriesAccompagnementService', () => {
         CategoriesAccompagnementService,
         {
           provide: getModelToken('CategoriesAccompagnement'),
-          useValue: CategoriesAccompagnement,
+          useValue: mockCategoriesAccompagnementModel,
         },
       ],
     }).compile();
@@ -24,4 +29,20 @@ describe('CategoriesAccompagnementService', () => {
   it('should be defined', () => {
     expect(service).toBeDefined();
   });
+
+  it('should create categorie accompagnement', async () => {
+    const data: CreateCategoriesAccompagnement = { name: 'test', modules: [{ id: 'Test', text: 'Text du test' }] };
+    const _doc = { _id: '5fbb92ef80a5c257dc0161f2', ...data };
+    mockCategoriesAccompagnementModel.create.mockResolvedValueOnce(_doc);
+    expect(await service.create(data)).toEqual(_doc);
+  });
+
+  it('should findAll structures', async () => {
+    const data: CreateCategoriesAccompagnement[] = [
+      { name: 'test', modules: [{ id: 'Test', text: 'Text du test' }] },
+      { name: 'test2', modules: [{ id: 'Test2', text: 'Text du test test 2' }] },
+    ];
+    mockCategoriesAccompagnementModel.find.mockResolvedValueOnce(data);
+    expect(await service.findAll()).toEqual(data);
+  });
 });
diff --git a/src/categories/services/categories-accompagnement.service.ts b/src/categories/services/categories-accompagnement.service.ts
index 830ad0c4552e0d68ccdccacda1f5bbbe0d63c3de..a8a41d17713196746f749b3e88c8dd9be0dbc328 100644
--- a/src/categories/services/categories-accompagnement.service.ts
+++ b/src/categories/services/categories-accompagnement.service.ts
@@ -11,11 +11,10 @@ export class CategoriesAccompagnementService {
   ) {}
 
   public async create(createDto: CreateCategoriesAccompagnement): Promise<CategoriesAccompagnement> {
-    const createdStructure = new this.structureModel(createDto);
-    return createdStructure.save();
+    return this.structureModel.create(createDto);
   }
 
   public async findAll(): Promise<CategoriesAccompagnement[]> {
-    return this.structureModel.find().exec();
+    return this.structureModel.find();
   }
 }
diff --git a/src/categories/services/categories-formations.service.spec.ts b/src/categories/services/categories-formations.service.spec.ts
index 4f079fdd4611597a976174206557113ead3b3194..6f7a63bdf1bd3e9bd2639fe6475d87cacd5bdffc 100644
--- a/src/categories/services/categories-formations.service.spec.ts
+++ b/src/categories/services/categories-formations.service.spec.ts
@@ -1,11 +1,16 @@
 import { getModelToken } from '@nestjs/mongoose';
 import { Test, TestingModule } from '@nestjs/testing';
-import { CategoriesFormations } from '../schemas/categoriesFormations.schema';
+import { CreateCategoriesFormations } from '../dto/create-categoriesFormations.dto';
 import { CategoriesFormationsService } from './categories-formations.service';
 
 describe('CategoriesFormationsService', () => {
   let service: CategoriesFormationsService;
 
+  const mockCategoriesFormationModel = {
+    create: jest.fn(),
+    find: jest.fn(),
+  };
+
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       imports: [],
@@ -13,7 +18,7 @@ describe('CategoriesFormationsService', () => {
         CategoriesFormationsService,
         {
           provide: getModelToken('CategoriesFormations'),
-          useValue: CategoriesFormations,
+          useValue: mockCategoriesFormationModel,
         },
       ],
     }).compile();
@@ -24,4 +29,53 @@ describe('CategoriesFormationsService', () => {
   it('should be defined', () => {
     expect(service).toBeDefined();
   });
+
+  it('should create categorie formation', async () => {
+    const data: CreateCategoriesFormations = {
+      name: 'test',
+      modules: [
+        {
+          id: '2',
+          display_id: '2',
+          display_name: 'Modules APTIC - n°2',
+          text: 'Les conduites à risques et les bons usages du numérique',
+          digest: 'Les conduites à risques et les bons usages du numérique - 02',
+        },
+      ],
+    };
+    const _doc = { _id: '5fbb92ef80a5c257dc0161f2', ...data };
+    mockCategoriesFormationModel.create.mockResolvedValueOnce(_doc);
+    expect(await service.create(data)).toEqual(_doc);
+  });
+
+  it('should findAll structures', async () => {
+    const data: CreateCategoriesFormations[] = [
+      {
+        name: 'test',
+        modules: [
+          {
+            id: '2',
+            display_id: '2',
+            display_name: 'Modules APTIC - n°2',
+            text: 'Les conduites à risques et les bons usages du numérique',
+            digest: 'Les conduites à risques et les bons usages du numérique - 02',
+          },
+        ],
+      },
+      {
+        name: 'test',
+        modules: [
+          {
+            id: '1',
+            display_id: '1',
+            display_name: 'Modules APTIC - n°1',
+            text: 'Les conduites à risques et les bons usages',
+            digest: 'Les conduites à risques et les bons usages - 01',
+          },
+        ],
+      },
+    ];
+    mockCategoriesFormationModel.find.mockResolvedValueOnce(data);
+    expect(await service.findAll()).toEqual(data);
+  });
 });
diff --git a/src/categories/services/categories-formations.service.ts b/src/categories/services/categories-formations.service.ts
index 71a6c1073ad5245541c651836b272195dd96397c..fab26f580d98135ce25f086a37136de2e2f9e095 100644
--- a/src/categories/services/categories-formations.service.ts
+++ b/src/categories/services/categories-formations.service.ts
@@ -9,15 +9,14 @@ export class CategoriesFormationsService {
   constructor(@InjectModel(CategoriesFormations.name) private structureModel: Model<CategoriesFormationsDocument>) {}
 
   public async create(createDto: CreateCategoriesFormations): Promise<CategoriesFormations> {
-    const createdStructure = new this.structureModel(createDto);
-    return createdStructure.save();
+    return this.structureModel.create(createDto);
   }
 
   public async findAll(): Promise<CategoriesFormations[]> {
-    return this.structureModel.find().exec();
+    return this.structureModel.find();
   }
 
-  public findOne(categoryId: string): Promise<any> {
+  public findOne(categoryId: string): Promise<CategoriesFormations> {
     return this.structureModel.findOne({ id: categoryId }).select({ 'modules.id': 1 }).exec();
   }
 }
diff --git a/src/categories/services/categories-others.service.spec.ts b/src/categories/services/categories-others.service.spec.ts
index 7c25eb3618f8bd75287bb29c7ebc52ba3256f33c..5de85c62c3669768f6064a8a2d54b2eb6a4a740e 100644
--- a/src/categories/services/categories-others.service.spec.ts
+++ b/src/categories/services/categories-others.service.spec.ts
@@ -1,11 +1,16 @@
 import { getModelToken } from '@nestjs/mongoose';
 import { Test, TestingModule } from '@nestjs/testing';
-import { CategoriesOthers } from '../schemas/categoriesOthers.schema';
+import { CreateCategoriesOthers } from '../dto/create-categoriesOthers.dto';
 import { CategoriesOthersService } from './categories-others.service';
 
 describe('CategoriesFormationsService', () => {
   let service: CategoriesOthersService;
 
+  const mockCategoriesOthersModel = {
+    create: jest.fn(),
+    find: jest.fn(),
+  };
+
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       imports: [],
@@ -13,7 +18,7 @@ describe('CategoriesFormationsService', () => {
         CategoriesOthersService,
         {
           provide: getModelToken('CategoriesOthers'),
-          useValue: CategoriesOthers,
+          useValue: mockCategoriesOthersModel,
         },
       ],
     }).compile();
@@ -24,4 +29,20 @@ describe('CategoriesFormationsService', () => {
   it('should be defined', () => {
     expect(service).toBeDefined();
   });
+
+  it('should create categorie accompagnement', async () => {
+    const data: CreateCategoriesOthers = { name: 'test', modules: [{ id: 'Test', text: 'Text du test' }] };
+    const _doc = { _id: '5fbb92ef80a5c257dc0161f2', ...data };
+    mockCategoriesOthersModel.create.mockResolvedValueOnce(_doc);
+    expect(await service.create(data)).toEqual(_doc);
+  });
+
+  it('should findAll structures', async () => {
+    const data: CreateCategoriesOthers[] = [
+      { name: 'test', modules: [{ id: 'Test', text: 'Text du test' }] },
+      { name: 'test2', modules: [{ id: 'Test2', text: 'Text du test test 2' }] },
+    ];
+    mockCategoriesOthersModel.find.mockResolvedValueOnce(data);
+    expect(await service.findAll()).toEqual(data);
+  });
 });
diff --git a/src/categories/services/categories-others.service.ts b/src/categories/services/categories-others.service.ts
index d229648e6d1b6fd8c8d1ad1dd07d059048c9c1c3..fd8b1b68d36d720784c98be2211a2e94dc088fdf 100644
--- a/src/categories/services/categories-others.service.ts
+++ b/src/categories/services/categories-others.service.ts
@@ -9,11 +9,10 @@ export class CategoriesOthersService {
   constructor(@InjectModel(CategoriesOthers.name) private structureModel: Model<CategoriesOthersDocument>) {}
 
   public async create(createDto: CreateCategoriesOthers): Promise<CategoriesOthers> {
-    const createdStructure = new this.structureModel(createDto);
-    return createdStructure.save();
+    return this.structureModel.create(createDto);
   }
 
   public async findAll(): Promise<CategoriesOthers[]> {
-    return this.structureModel.find().exec();
+    return this.structureModel.find();
   }
 }
diff --git a/src/newsletter/newsletter.service.spec.ts b/src/newsletter/newsletter.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..15cfedd88581e257b359f3297886181982df19a3
--- /dev/null
+++ b/src/newsletter/newsletter.service.spec.ts
@@ -0,0 +1,137 @@
+import { HttpModule, HttpStatus } from '@nestjs/common';
+import { getModelToken } from '@nestjs/mongoose';
+import { Test, TestingModule } from '@nestjs/testing';
+import { INewsletterSubscription } from './interface/newsletter-subscription.interface';
+import { NewsletterSubscription } from './newsletter-subscription.schema';
+import { NewsletterService } from './newsletter.service';
+describe('NewsletterService', () => {
+  let service: NewsletterService;
+
+  const mockNewsletterModel = {
+    create: jest.fn(),
+    deleteOne: jest.fn(),
+    countDocuments: jest.fn(),
+    findOne: jest.fn(),
+    exec: jest.fn(),
+    find: jest.fn(),
+  };
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [HttpModule],
+      providers: [
+        NewsletterService,
+        {
+          provide: getModelToken(NewsletterSubscription.name),
+          useValue: mockNewsletterModel,
+        },
+      ],
+    }).compile();
+
+    service = module.get<NewsletterService>(NewsletterService);
+  });
+
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+
+  describe('newsletterSubscribe', () => {
+    it('it should not add subscription for email test2@test.com : already exist', async () => {
+      const result = { email: 'test2@test.com' } as INewsletterSubscription;
+      jest
+        .spyOn(service, 'findOne')
+        .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result);
+      try {
+        await service.newsletterSubscribe('test2@test.com');
+        // Fail test if above expression doesn't throw anything.
+        expect(true).toBe(false);
+      } catch (e) {
+        expect(e.message).toEqual('Email already exists');
+        expect(e.status).toEqual(HttpStatus.BAD_REQUEST);
+      }
+    });
+    it('it should add a subscription for email test2@test.com', async () => {
+      const result: INewsletterSubscription = { email: 'test2@test.com' } as INewsletterSubscription;
+      const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' };
+      jest
+        .spyOn(service, 'findOne')
+        .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => undefined)
+        .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result);
+      mockNewsletterModel.create.mockResolvedValueOnce(_doc);
+
+      const subscription = await service.newsletterSubscribe('test2@test.com');
+      expect(subscription).toEqual({ email: 'test2@test.com' });
+    });
+  });
+  describe('newsletterUnsubscribe', () => {
+    it('it should not remove subscription for email test@test.com : does not exist', async () => {
+      const result: INewsletterSubscription = undefined;
+      jest
+        .spyOn(service, 'findOne')
+        .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result);
+      try {
+        await service.newsletterUnsubscribe('test@test.com');
+        // Fail test if above expression doesn't throw anything.
+        expect(true).toBe(false);
+      } catch (e) {
+        expect(e.message).toEqual('Invalid email');
+        expect(e.status).toEqual(HttpStatus.BAD_REQUEST);
+      }
+    });
+    it('it should remove a subscription for email test2@test.com', async () => {
+      const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' };
+      const result = {
+        email: 'test2@test.com',
+        deleteOne: async () => _doc,
+      } as INewsletterSubscription;
+      jest
+        .spyOn(service, 'findOne')
+        .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result);
+
+      const subscription = await service.newsletterUnsubscribe('test2@test.com');
+      expect(subscription).toEqual(_doc);
+    });
+  });
+
+  describe('countNewsletterSubscriptions', () => {
+    it('it should count subscriptions', async () => {
+      mockNewsletterModel.countDocuments.mockResolvedValueOnce(69);
+      const count = await service.countNewsletterSubscriptions();
+
+      expect(count).toEqual(69);
+    });
+  });
+
+  describe('findOne', () => {
+    it('it should not find a subscription with email test@test.com', async () => {
+      mockNewsletterModel.findOne.mockResolvedValueOnce(undefined);
+      const findOneEmail = await service.findOne('test@test.com');
+      expect(findOneEmail).toEqual(undefined);
+    });
+    it('it should find a subscription with email test2@test.com', async () => {
+      const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' } as INewsletterSubscription;
+      mockNewsletterModel.findOne.mockResolvedValueOnce(_doc);
+      const findOneEmail = await service.findOne('test2@test.com');
+      expect(findOneEmail).toEqual(_doc);
+    });
+  });
+  describe('findAll', () => {
+    it('it should find all', async () => {
+      const _docs = [{ _id: 'a1aaaaa1a1', email: 'test2@test.com' } as INewsletterSubscription];
+      mockNewsletterModel.find.mockResolvedValueOnce(_docs);
+      const findOneEmail = await service.findAll();
+      expect(findOneEmail).toEqual(_docs);
+    });
+  });
+  describe('searchNewsletterSubscription', () => {
+    it('it should find 2 search result', async () => {
+      const _docs = [
+        { _id: 'a1aaaaa1a1', email: 'test2@test.com' } as INewsletterSubscription,
+        { _id: 'bbbbb', email: 'test@test.com' } as INewsletterSubscription,
+      ];
+      mockNewsletterModel.find.mockResolvedValueOnce(_docs);
+      const findOneEmail = await service.searchNewsletterSubscription('test');
+      expect(findOneEmail.length).toBe(2);
+    });
+  });
+});
diff --git a/src/newsletter/newsletter.service.ts b/src/newsletter/newsletter.service.ts
index 89020eddbaa0808f25f0cedd9c30fba7bc29d1f0..c5f8363fbfc83d175b1fe5377e0de76386010e27 100644
--- a/src/newsletter/newsletter.service.ts
+++ b/src/newsletter/newsletter.service.ts
@@ -15,40 +15,31 @@ export class NewsletterService {
     if (existingEmail) {
       throw new HttpException('Email already exists', HttpStatus.BAD_REQUEST);
     }
-    const createSubscription = new this.newsletterSubscriptionModel({ email: email });
-    createSubscription.save();
-    return await this.findOne(email);
+    await this.newsletterSubscriptionModel.create({ email: email });
+    return this.findOne(email);
   }
 
   public async newsletterUnsubscribe(email: string): Promise<NewsletterSubscription> {
-    const subscription = await this.newsletterSubscriptionModel.findOne({ email: email }).exec();
+    const subscription = await this.findOne(email);
     if (!subscription) {
       throw new HttpException('Invalid email', HttpStatus.BAD_REQUEST);
     }
     return subscription.deleteOne();
   }
 
-  public async findOne(mail: string): Promise<NewsletterSubscription | undefined> {
-    return this.newsletterSubscriptionModel.findOne({ email: mail }).exec();
+  public async findOne(mail: string): Promise<INewsletterSubscription | undefined> {
+    return this.newsletterSubscriptionModel.findOne({ email: mail });
   }
 
   public async searchNewsletterSubscription(searchString: string): Promise<NewsletterSubscriptionDocument[]> {
-    return this.newsletterSubscriptionModel.find({ email: new RegExp(searchString, 'i') }).exec();
+    return this.newsletterSubscriptionModel.find({ email: new RegExp(searchString, 'i') });
   }
 
   public async countNewsletterSubscriptions(): Promise<number> {
-    return this.newsletterSubscriptionModel.countDocuments({}).exec();
-  }
-
-  public async deleteOneEmail(mail: string): Promise<NewsletterSubscription | undefined> {
-    const subscription = await this.newsletterSubscriptionModel.findOne({ email: mail }).exec();
-    if (!subscription) {
-      throw new HttpException('Invalid  email', HttpStatus.BAD_REQUEST);
-    }
-    return subscription.deleteOne();
+    return this.newsletterSubscriptionModel.countDocuments({});
   }
 
   public async findAll(): Promise<NewsletterSubscription[]> {
-    return await this.newsletterSubscriptionModel.find().exec();
+    return this.newsletterSubscriptionModel.find();
   }
 }
diff --git a/src/posts/posts.controller.spec.ts b/src/posts/posts.controller.spec.ts
index 39b091029861448339fa4a8c755dd634664a6d77..56371cebb1628a0cb17190a7e65f98ea7e199903 100644
--- a/src/posts/posts.controller.spec.ts
+++ b/src/posts/posts.controller.spec.ts
@@ -1,17 +1,38 @@
-import { HttpModule } from '@nestjs/common';
+import { HttpModule, HttpService } from '@nestjs/common';
 import { Test, TestingModule } from '@nestjs/testing';
+import { of } from 'rxjs';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { PostsController } from './posts.controller';
 import { PostsService } from './posts.service';
-import { PostWithMeta } from './schemas/postWithMeta.schema';
+import { AxiosResponse } from 'axios';
 
 describe('PostsController', () => {
   let controller: PostsController;
 
+  const httpServiceMock = {
+    get: jest.fn(),
+  };
+
+  const postServiceMock = {
+    getLocationTags: jest.fn(),
+    getPublicTags: jest.fn(),
+    getRegularTags: jest.fn(),
+    formatPosts: jest.fn(),
+  };
+
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       imports: [ConfigurationModule, HttpModule],
-      providers: [PostsService],
+      providers: [
+        {
+          provide: PostsService,
+          useValue: postServiceMock,
+        },
+        {
+          provide: HttpService,
+          useValue: httpServiceMock,
+        },
+      ],
       controllers: [PostsController],
     }).compile();
 
@@ -22,23 +43,383 @@ describe('PostsController', () => {
     expect(controller).toBeDefined();
   });
 
-  it('should get pending attachments', async () => {
-    const result:PostWithMeta = {posts:[], meta:{pagination: null}};
-    const query = "";
-    jest.spyOn(controller, 'findAll').mockImplementation(async (): Promise<any> => result);
-    expect(await controller.findAll(query)).toBe(result);
+  describe('findAll', () => {
+    it('should get all posts', async () => {
+      const query = '';
+      const result: AxiosResponse = {
+        data: {
+          posts: [
+            {
+              id: '61c4847b0ff4550001505090',
+              uuid: 'f4ee5a37-a343-4cad-8a32-3f6cf87f9569',
+              title: 'Only feature image',
+              slug: 'only-feature-image',
+              html: '<p>Test</p>',
+              comment_id: '61c4847b0ff4550001505090',
+              feature_image: 'http://localhost:2368/content/images/2021/12/dacc-4.png',
+              featured: false,
+              visibility: 'public',
+              email_recipient_filter: 'none',
+              created_at: '2021-12-23T14:15:23.000+00:00',
+              updated_at: '2021-12-23T14:15:45.000+00:00',
+              published_at: '2021-12-23T14:15:45.000+00:00',
+              custom_excerpt: null,
+              codeinjection_head: null,
+              codeinjection_foot: null,
+              custom_template: null,
+              canonical_url: null,
+              tags: [Array],
+              authors: [Array],
+              primary_author: [Object],
+              primary_tag: [Object],
+              url: 'http://localhost:2368/only-feature-image/',
+              excerpt:
+                '« Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus.\n' +
+                'Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed,\n' +
+                'dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper\n' +
+                'congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est\n' +
+                'eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu\n' +
+                'massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut\n' +
+                'in risus volutpat libero pharetra tem',
+              reading_time: 2,
+              access: true,
+              send_email_when_published: false,
+              og_image: null,
+              og_title: null,
+              og_description: null,
+              twitter_image: null,
+              twitter_title: null,
+              twitter_description: null,
+              meta_title: null,
+              meta_description: null,
+              email_subject: null,
+              frontmatter: null,
+            },
+            {
+              id: '61c4847b0ff4550001505090',
+              uuid: 'f4ee5a37-a343-4cad-8a32-3f6cf87f9569',
+              title: 'Only test image',
+              slug: 'only-test-image',
+              html: '<p>Test 2</p>',
+              comment_id: '61c4847b0ff4550001505090',
+              feature_image: 'http://localhost:2368/content/images/2021/12/test.png',
+              featured: false,
+              visibility: 'public',
+              email_recipient_filter: 'none',
+              created_at: '2021-12-23T14:15:23.000+00:00',
+              updated_at: '2021-12-23T14:15:45.000+00:00',
+              published_at: '2021-12-23T14:15:45.000+00:00',
+              custom_excerpt: null,
+              codeinjection_head: null,
+              codeinjection_foot: null,
+              custom_template: null,
+              canonical_url: null,
+              tags: [Array],
+              authors: [Array],
+              primary_author: [Object],
+              primary_tag: [Object],
+              url: 'http://localhost:2368/only-feature-image/',
+              excerpt:
+                '« Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus.\n' +
+                'Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed,\n' +
+                'dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper\n' +
+                'congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est\n' +
+                'eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu\n' +
+                'massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut\n' +
+                'in risus volutpat libero pharetra tem',
+              reading_time: 2,
+              access: true,
+              send_email_when_published: false,
+              og_image: null,
+              og_title: null,
+              og_description: null,
+              twitter_image: null,
+              twitter_title: null,
+              twitter_description: null,
+              meta_title: null,
+              meta_description: null,
+              email_subject: null,
+              frontmatter: null,
+            },
+            {
+              id: '61c4847b0ff4550001505090',
+              uuid: 'f4ee5a37-a343-4cad-8a32-3f6cf87f9569',
+              title: 'Only toto image',
+              slug: 'only-toto-image',
+              html: '<p>Test 3</p>',
+              comment_id: '61c4847b0ff4550001505090',
+              feature_image: 'http://localhost:2368/content/images/2021/12/dacc-4.png',
+              featured: false,
+              visibility: 'public',
+              email_recipient_filter: 'none',
+              created_at: '2021-12-23T14:15:23.000+00:00',
+              updated_at: '2021-12-23T14:15:45.000+00:00',
+              published_at: '2021-12-23T14:15:45.000+00:00',
+              custom_excerpt: null,
+              codeinjection_head: null,
+              codeinjection_foot: null,
+              custom_template: null,
+              canonical_url: null,
+              tags: [Array],
+              authors: [Array],
+              primary_author: [Object],
+              primary_tag: [Object],
+              url: 'http://localhost:2368/only-feature-image/',
+              excerpt:
+                '« Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus.\n' +
+                'Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed,\n' +
+                'dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper\n' +
+                'congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est\n' +
+                'eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu\n' +
+                'massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut\n' +
+                'in risus volutpat libero pharetra tem',
+              reading_time: 2,
+              access: true,
+              send_email_when_published: false,
+              og_image: null,
+              og_title: null,
+              og_description: null,
+              twitter_image: null,
+              twitter_title: null,
+              twitter_description: null,
+              meta_title: null,
+              meta_description: null,
+              email_subject: null,
+              frontmatter: null,
+            },
+          ],
+          meta: { pagination: { page: 1, limit: 15, pages: 1, total: 2, next: null, prev: null } },
+        },
+        status: 200,
+        statusText: 'OK',
+        headers: {},
+        config: {},
+      };
+      jest.spyOn(httpServiceMock, 'get').mockImplementationOnce(() => of(result));
+      const response = await controller.findAll(query);
+      expect(response.posts.length).toEqual(3);
+      expect(response.meta.pagination.limit).toEqual(15);
+      expect(response.meta.pagination.page).toEqual(1);
+      expect(response.meta.pagination.total).toEqual(2);
+    });
   });
 
-  it('should get pending attachments', async () => {
-    const result = { posts:[] };
-    jest.spyOn(controller, 'findAllTags').mockImplementation(async (): Promise<any> => result);
-    expect(await controller.findAllTags()).toBe(result);
+  describe('findAllTags', () => {
+    it('should get all tags', async () => {
+      postServiceMock.getLocationTags.mockImplementationOnce(() => [
+        {
+          id: '61b74b2c0d3b9800018ca3df',
+          name: 'oullins',
+          slug: 'oullins',
+          description: 'commune',
+          feature_image: null,
+          visibility: 'public',
+          og_image: null,
+          og_title: null,
+          og_description: null,
+          twitter_image: null,
+          twitter_title: null,
+          twitter_description: null,
+          meta_title: null,
+          meta_description: null,
+          codeinjection_head: null,
+          codeinjection_foot: null,
+          canonical_url: null,
+          accent_color: null,
+          created_at: '2021-12-13T13:31:24.000Z',
+          updated_at: '2021-12-13T13:31:25.000Z',
+          url: 'http://localhost:2368/tag/oullins/',
+        },
+        {
+          id: '61b74b2c0d3b9800018ca3df',
+          name: 'oullins',
+          slug: 'oullins',
+          description: 'commune',
+          feature_image: null,
+          visibility: 'public',
+          og_image: null,
+          og_title: null,
+          og_description: null,
+          twitter_image: null,
+          twitter_title: null,
+          twitter_description: null,
+          meta_title: null,
+          meta_description: null,
+          codeinjection_head: null,
+          codeinjection_foot: null,
+          canonical_url: null,
+          accent_color: null,
+          created_at: '2021-12-13T13:31:24.000Z',
+          updated_at: '2021-12-13T13:31:25.000Z',
+          url: 'http://localhost:2368/tag/oullins/',
+        },
+        {
+          id: '61b74b2c0d3b9800018ca3e0',
+          name: 'Bron',
+          slug: 'bron',
+          description: 'commune',
+          feature_image: null,
+          visibility: 'public',
+          og_image: null,
+          og_title: null,
+          og_description: null,
+          twitter_image: null,
+          twitter_title: null,
+          twitter_description: null,
+          meta_title: null,
+          meta_description: null,
+          codeinjection_head: null,
+          codeinjection_foot: null,
+          canonical_url: null,
+          accent_color: null,
+          created_at: '2021-12-13T13:31:24.000Z',
+          updated_at: '2021-12-13T13:31:24.000Z',
+          url: 'http://localhost:2368/404/',
+        },
+      ]);
+      postServiceMock.getPublicTags.mockImplementationOnce(() => [
+        {
+          id: '61b74b2d0d3b9800018ca3f6',
+          name: 'Séniors (+ de 65ans)',
+          slug: 'seniors-de-65ans',
+          description: 'public',
+          feature_image: null,
+          visibility: 'public',
+          og_image: null,
+          og_title: null,
+          og_description: null,
+          twitter_image: null,
+          twitter_title: null,
+          twitter_description: null,
+          meta_title: null,
+          meta_description: null,
+          codeinjection_head: null,
+          codeinjection_foot: null,
+          canonical_url: null,
+          accent_color: null,
+          created_at: '2021-12-13T13:31:25.000Z',
+          updated_at: '2021-12-13T13:31:25.000Z',
+          url: 'http://localhost:2368/404/',
+        },
+        {
+          id: '61b74b2d0d3b9800018ca3f7',
+          name: 'Allophones',
+          slug: 'allophones',
+          description: 'public',
+          feature_image: null,
+          visibility: 'public',
+          og_image: null,
+          og_title: null,
+          og_description: null,
+          twitter_image: null,
+          twitter_title: null,
+          twitter_description: null,
+          meta_title: null,
+          meta_description: null,
+          codeinjection_head: null,
+          codeinjection_foot: null,
+          canonical_url: null,
+          accent_color: null,
+          created_at: '2021-12-13T13:31:25.000Z',
+          updated_at: '2021-12-13T13:31:25.000Z',
+          url: 'http://localhost:2368/404/',
+        },
+      ]);
+      postServiceMock.getRegularTags.mockImplementationOnce(() => [
+        {
+          id: '61b74b2d0d3b9800018ca3fa',
+          name: 'Études',
+          slug: 'etudes',
+          description: null,
+          feature_image: null,
+          visibility: 'public',
+          og_image: null,
+          og_title: null,
+          og_description: null,
+          twitter_image: null,
+          twitter_title: null,
+          twitter_description: null,
+          meta_title: null,
+          meta_description: null,
+          codeinjection_head: null,
+          codeinjection_foot: null,
+          canonical_url: null,
+          accent_color: null,
+          created_at: '2021-12-13T13:31:25.000Z',
+          updated_at: '2021-12-13T13:31:25.000Z',
+          url: 'http://localhost:2368/tag/etudes/',
+        },
+      ]);
+      const result = await controller.findAllTags();
+      expect(result.commune.length).toBe(3);
+      expect(result.others.length).toBe(1);
+      expect(result.public.length).toBe(2);
+    });
   });
 
-  it('should get pending attachments', async () => {
-    const result = { public:[], comune:[], others:[] };
-    const id = "78945945"
-    jest.spyOn(controller, 'getPostbyId').mockImplementation(async (): Promise<any> => result);
-    expect(await controller.getPostbyId(id)).toBe(result);
+  describe('getPostbyId', () => {
+    it('should get post Hello by id 61c4847b0ff4550001505090', async () => {
+      const data = [
+        {
+          id: '61c4847b0ff4550001505090',
+          uuid: 'f4ee5a37-a343-4cad-8a32-3f6cf87f9569',
+          title: 'Hello',
+          slug: 'hello',
+          html: '<p>Test</p>',
+          comment_id: '61c4847b0ff4550001505090',
+          feature_image: 'http://localhost:2368/content/images/2021/12/dacc-4.png',
+          featured: false,
+          visibility: 'public',
+          email_recipient_filter: 'none',
+          created_at: '2021-12-23T14:15:23.000+00:00',
+          updated_at: '2021-12-23T14:15:45.000+00:00',
+          published_at: '2021-12-23T14:15:45.000+00:00',
+          custom_excerpt: null,
+          codeinjection_head: null,
+          codeinjection_foot: null,
+          custom_template: null,
+          canonical_url: null,
+          tags: [Array],
+          authors: [Array],
+          primary_author: [Object],
+          primary_tag: [Object],
+          url: 'http://localhost:2368/hello/',
+          excerpt:
+            '« Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus.\n' +
+            'Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed,\n' +
+            'dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper\n' +
+            'congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est\n' +
+            'eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu\n' +
+            'massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut\n' +
+            'in risus volutpat libero pharetra tem',
+          reading_time: 2,
+          access: true,
+          send_email_when_published: false,
+          og_image: null,
+          og_title: null,
+          og_description: null,
+          twitter_image: null,
+          twitter_title: null,
+          twitter_description: null,
+          meta_title: null,
+          meta_description: null,
+          email_subject: null,
+          frontmatter: null,
+        },
+      ];
+      const axiosResult: AxiosResponse = {
+        data: {
+          posts: data,
+        },
+        status: 200,
+        statusText: 'OK',
+        headers: {},
+        config: {},
+      };
+      httpServiceMock.get.mockImplementationOnce(() => of(axiosResult));
+      postServiceMock.formatPosts.mockImplementationOnce(() => data);
+      const result = await (await controller.getPostbyId('61c4847b0ff4550001505090')).toPromise();
+      expect(result).toStrictEqual({ posts: [data] });
+    });
   });
 });
diff --git a/src/posts/posts.controller.ts b/src/posts/posts.controller.ts
index d947390c55e7a81214f5228c8d558d23dab0b2a8..0652fc5ae92355154d2778545387241f17ac6a53 100644
--- a/src/posts/posts.controller.ts
+++ b/src/posts/posts.controller.ts
@@ -9,6 +9,7 @@ import { PostWithMeta } from './schemas/postWithMeta.schema';
 
 @Controller('posts')
 export class PostsController {
+  private readonly logger = new Logger(PostsController.name);
   constructor(private readonly httpService: HttpService, private readonly postsService: PostsService) {}
 
   @Get()
@@ -36,7 +37,7 @@ export class PostsController {
       .pipe(
         map((response) => response.data),
         catchError((err) => {
-          Logger.error(err);
+          this.logger.error(err);
           throw new HttpException('Invalid ghost configuration', HttpStatus.BAD_REQUEST);
         })
       );
diff --git a/src/posts/posts.service.spec.ts b/src/posts/posts.service.spec.ts
index 5b01e555650ff0b0f58f1a33e8f3f352846d4fbe..90d17e16278895ed92a474666fda924c18c171d9 100644
--- a/src/posts/posts.service.spec.ts
+++ b/src/posts/posts.service.spec.ts
@@ -1,10 +1,210 @@
 import { HttpModule } from '@nestjs/common';
 import { Test, TestingModule } from '@nestjs/testing';
 import { ConfigurationModule } from '../configuration/configuration.module';
+import { TagEnum } from './enums/tag.enum';
 import { PostsService } from './posts.service';
+import { Tag } from './schemas/tag.schema';
+import * as _ from 'lodash';
+import { Post } from './schemas/post.schema';
 
 describe('PostsService', () => {
   let service: PostsService;
+  // let configService: ConfigurationServiceMock;
+
+  const locationtags = [
+    {
+      id: '61b74b2c0b9800018ca3df',
+      name: 'oullins',
+      slug: 'oullins',
+      description: 'commune',
+      feature_image: null,
+      visibility: 'public',
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      canonical_url: null,
+      accent_color: null,
+      created_at: '2021-12-13T13:31:24.000Z',
+      updated_at: '2021-12-13T13:31:25.000Z',
+      url: 'http://localhost:2368/tag/oullins/',
+    },
+    {
+      id: '61b74b2c0d9800018ca3df',
+      name: 'oullins',
+      slug: 'oullins',
+      description: 'commune',
+      feature_image: null,
+      visibility: 'public',
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      canonical_url: null,
+      accent_color: null,
+      created_at: '2021-12-13T13:31:24.000Z',
+      updated_at: '2021-12-13T13:31:25.000Z',
+      url: 'http://localhost:2368/tag/oullins/',
+    },
+    {
+      id: '61b74b2d3b9800018ca3e0',
+      name: 'Bron',
+      slug: 'bron',
+      description: 'commune',
+      feature_image: null,
+      visibility: 'public',
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      canonical_url: null,
+      accent_color: null,
+      created_at: '2021-12-13T13:31:24.000Z',
+      updated_at: '2021-12-13T13:31:24.000Z',
+      url: 'http://localhost:2368/404/',
+    },
+  ];
+
+  const publictags = [
+    {
+      id: '61b74b2d0d3b9800018ca3f6',
+      name: 'Séniors (+ de 65ans)',
+      slug: 'seniors-de-65ans',
+      description: 'public',
+      feature_image: null,
+      visibility: 'public',
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      canonical_url: null,
+      accent_color: null,
+      created_at: '2021-12-13T13:31:25.000Z',
+      updated_at: '2021-12-13T13:31:25.000Z',
+      url: 'http://localhost:2368/404/',
+    },
+    {
+      id: '61b74b2d0d3b98000ca3f7',
+      name: 'Allophones',
+      slug: 'allophones',
+      description: 'public',
+      feature_image: null,
+      visibility: 'public',
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      canonical_url: null,
+      accent_color: null,
+      created_at: '2021-12-13T13:31:25.000Z',
+      updated_at: '2021-12-13T13:31:25.000Z',
+      url: 'http://localhost:2368/404/',
+    },
+  ];
+
+  const otherTags = [
+    {
+      id: '61b74b2d0d3b980001a3fa',
+      name: 'Études',
+      slug: 'etudes',
+      description: null,
+      feature_image: null,
+      visibility: 'public',
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      canonical_url: null,
+      accent_color: null,
+      created_at: '2021-12-13T13:31:25.000Z',
+      updated_at: '2021-12-13T13:31:25.000Z',
+      url: 'http://localhost:2368/tag/etudes/',
+    },
+    {
+      id: '61b74b2d0d3b980001a3fa',
+      name: 'A la une',
+      slug: 'a-la-une',
+      description: null,
+      feature_image: null,
+      visibility: 'public',
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      canonical_url: null,
+      accent_color: null,
+      created_at: '2021-12-13T13:31:25.000Z',
+      updated_at: '2021-12-13T13:31:25.000Z',
+      url: 'http://localhost:2368/tag/a-la-une/',
+    },
+    {
+      id: '61b74b2d0d3b980001a3fa',
+      name: 'Infos',
+      slug: 'infos',
+      description: null,
+      feature_image: null,
+      visibility: 'public',
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      canonical_url: null,
+      accent_color: null,
+      created_at: '2021-12-13T13:31:25.000Z',
+      updated_at: '2021-12-13T13:31:25.000Z',
+      url: 'http://localhost:2368/tag/infos/',
+    },
+  ];
+
+  const tagsData = [...locationtags, ...publictags, ...otherTags];
 
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
@@ -13,9 +213,114 @@ describe('PostsService', () => {
     }).compile();
 
     service = module.get<PostsService>(PostsService);
+    jest.spyOn(service, 'getTags').mockImplementationOnce(async (): Promise<Tag[]> => tagsData);
   });
 
   it('should be defined', () => {
     expect(service).toBeDefined();
   });
+
+  it('should get tags', async () => {
+    expect(await service.getTags()).toEqual(tagsData);
+  });
+
+  it('should get location tags', async () => {
+    expect(await service.getLocationTags()).toEqual(locationtags);
+  });
+
+  it('should get public tags', async () => {
+    expect(await service.getPublicTags()).toEqual(publictags);
+  });
+
+  it('should get regular tags', async () => {
+    expect(await service.getRegularTags()).toEqual([otherTags[1], otherTags[2], otherTags[0]]);
+  });
+  describe('arraymove', () => {
+    it('should order tags for display: A La Une tag should be set to first index', () => {
+      const dataCopy = [...otherTags];
+      service.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.aLaUne }), 0);
+      expect(dataCopy).toEqual([otherTags[1], otherTags[0], otherTags[2]]);
+    });
+    it('should order tags for display: Info tag should be set to second index', () => {
+      const dataCopy = [...otherTags];
+      expect(service.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.infos }), 1)).toEqual([
+        otherTags[0],
+        otherTags[2],
+        otherTags[1],
+      ]);
+    });
+    it('should order tags for display: A La Une tag should be set to first index and Info to second', () => {
+      const dataCopy = [...otherTags];
+      service.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.aLaUne }), 0);
+      expect(service.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.infos }), 1)).toEqual([
+        otherTags[1],
+        otherTags[2],
+        otherTags[0],
+      ]);
+    });
+  });
+
+  describe('formatPosts', () => {
+    const postToFormat: Post = {
+      id: '61c4847b0ff4550001505090',
+      uuid: 'f4ee5a37-a343-4cad-8a32-3f6cf87f9569',
+      title: 'Only feature image',
+      slug: 'only-feature-image',
+      html: '<p>Test</p>',
+      comment_id: '61c4847b0ff4550001505090',
+      feature_image: 'http://localhost:2368/content/images/2021/12/dacc-4.png',
+      featured: false,
+      visibility: 'public',
+      email_recipient_filter: 'none',
+      created_at: '2021-12-23T14:15:23.000+00:00',
+      updated_at: '2021-12-23T14:15:45.000+00:00',
+      published_at: '2021-12-23T14:15:45.000+00:00',
+      custom_excerpt: null,
+      codeinjection_head: null,
+      codeinjection_foot: null,
+      custom_template: null,
+      canonical_url: null,
+      tags: [],
+      authors: [],
+      primary_author: [],
+      primary_tag: [],
+      url: 'http://localhost:2368/only-feature-image/',
+      excerpt:
+        '« Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus.\n' +
+        'Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed,\n' +
+        'dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper\n' +
+        'congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est\n' +
+        'eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu\n' +
+        'massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut\n' +
+        'in risus volutpat libero pharetra tem',
+      reading_time: '2',
+      access: true,
+      send_email_when_published: false,
+      og_image: null,
+      og_title: null,
+      og_description: null,
+      twitter_image: null,
+      twitter_title: null,
+      twitter_description: null,
+      meta_title: null,
+      meta_description: null,
+      email_subject: null,
+      frontmatter: null,
+    };
+    it('should format post with no custom expert', () => {
+      const objCp = { ...postToFormat };
+      let result = { ...postToFormat };
+      result.excerpt = 'Inconnu';
+      result.feature_image = 'https://localhost/blog/content/images/2021/12/dacc-4.png';
+      expect(service.formatPosts(objCp)).toEqual(result);
+    });
+    it('should format post with custom expert', () => {
+      let objCp = { ...postToFormat };
+      objCp.custom_excerpt = 'Toto';
+      let result = { ...postToFormat };
+      result.custom_excerpt = 'Toto';
+      result.feature_image = 'https://localhost/blog/content/images/2021/12/dacc-4.png';
+      expect(service.formatPosts(objCp)).toEqual(result);
+    });
+  });
 });
diff --git a/src/posts/schemas/post.schema.ts b/src/posts/schemas/post.schema.ts
index 3e2ac2ca992fc0be11e97e73b2e13f6730a6aa75..6e2e8cc22f9bd07f2d0c75f0c3327d7e2a91b10a 100644
--- a/src/posts/schemas/post.schema.ts
+++ b/src/posts/schemas/post.schema.ts
@@ -27,4 +27,13 @@ export class Post {
   meta_title: string;
   meta_description: string;
   email_subject: string;
+  codeinjection_head: string;
+  codeinjection_foot: string;
+  custom_template: string;
+  canonical_url: string;
+  tags: [];
+  authors: [];
+  primary_author: [];
+  primary_tag: [];
+  frontmatter: [];
 }
diff --git a/src/structures/services/aptic-structures.service.ts b/src/structures/services/aptic-structures.service.ts
index 46098d0e83ec09f6217ff562f3318f7c77b1c89f..978a2ecf9d3093ec35e75498b9c863db7cfd6113 100644
--- a/src/structures/services/aptic-structures.service.ts
+++ b/src/structures/services/aptic-structures.service.ts
@@ -17,6 +17,7 @@ import { StructuresSearchService } from './structures-search.service';
 
 @Injectable()
 export class ApticStructuresService {
+  private readonly logger = new Logger(ApticStructuresService.name);
   constructor(
     private readonly httpService: HttpService,
     private readonly userService: UsersService,
@@ -46,13 +47,15 @@ export class ApticStructuresService {
                 this.createApticStructures(structure);
               },
               (err) => {
-                Logger.log(err);
+                this.logger.log(err);
               }
             );
           });
         },
         (err) => {
-          Logger.log(`getApticStructures error on postal code: ${postalCode}. Code: ${err}`);
+          this.logger.log(
+            `formatApticStructures | getApticStructures error on postal code: ${postalCode}. Code: ${err}`
+          );
         }
       );
     });
@@ -65,7 +68,7 @@ export class ApticStructuresService {
   private async createApticStructures(structure: ApticStructure): Promise<any> {
     this.structureAlreadyExist(structure).then(async (exist) => {
       if (!exist) {
-        Logger.log(`Create structure : ${structure.name}`, 'ApticStructuresService - createApticStructures');
+        this.logger.log(`createApticStructures | Create structure : ${structure.name}`);
         const createdStructure = new this.structureModel();
         // Known fields
         createdStructure.structureName = structure.name;
@@ -183,7 +186,7 @@ export class ApticStructuresService {
   public getMetopoleMunicipality(): void {
     const req =
       'https://download.data.grandlyon.com/ws/grandlyon/adr_voie_lieu.adrcomgl/all.json?maxfeatures=-1&start=1';
-    Logger.log(`Request : ${req}`, 'ApticStructuresService - getMetopoleMunicipality');
+    this.logger.log(`getMetopoleMunicipality | Request : ${req}`, '');
     this.httpService.get(encodeURI(req)).subscribe(
       (data) => {
         const inseeArray = data.data.values.map((municipality) => {
@@ -196,19 +199,19 @@ export class ApticStructuresService {
           this.formatApticStructures(postalCodeArray);
         });
       },
-      (err) => Logger.error(err)
+      (err) => this.logger.error(err)
     );
   }
 
   public getPostalCodeWithINSEE(inseeCode: string): Observable<AxiosResponse<any>> {
     const req = `https://geo.api.gouv.fr/communes/${inseeCode}?fields=codesPostaux&format=json`;
-    Logger.log(`Request : ${req}`, 'ApticStructuresService - getMetopoleMunicipality');
+    this.logger.debug(`getMetopoleMunicipality | Request : ${req}`);
     return this.httpService.get(encodeURI(req));
   }
 
   public getApticStructures(postalCodeData: string): Observable<AxiosResponse<{ presencePoints: ApticStructure[] }>> {
     const req = `https://aptisearch-api.aptic.fr/v1/postal-code/${postalCodeData}`;
-    Logger.log(`Request : ${req}`, 'ApticStructuresService');
+    this.logger.debug(`getApticStructures | Request : ${req}`);
     return this.httpService.get(req, {
       headers: {
         api_key: process.env.APTIC_TOKEN,
@@ -221,7 +224,7 @@ export class ApticStructuresService {
       rejectUnauthorized: false,
     });
     const req = `https://aptisearch-api.aptic.fr/v1/catalog/${catalogId}/services`;
-    Logger.log(`Request : ${req}`, 'ApticStructuresService');
+    this.logger.log(`getApticStructureOffer | Request : ${req}`);
     return this.httpService.get(req, {
       httpsAgent: agent,
       headers: {
diff --git a/src/structures/services/structure.service.spec.ts b/src/structures/services/structure.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..82128e4105f934f8062832a0b90b5cc21b25ab4e
--- /dev/null
+++ b/src/structures/services/structure.service.spec.ts
@@ -0,0 +1,109 @@
+import { HttpModule, HttpStatus } from '@nestjs/common';
+import { ConfigModule } from '@nestjs/config';
+import { ElasticsearchService } from '@nestjs/elasticsearch';
+import { getModelToken } from '@nestjs/mongoose';
+import { Test, TestingModule } from '@nestjs/testing';
+import { UsersServiceMock } from '../../../test/mock/services/user.mock.service';
+import { ConfigurationService } from '../../configuration/configuration.service';
+import { MailerModule } from '../../mailer/mailer.module';
+import { MailerService } from '../../mailer/mailer.service';
+import { SearchModule } from '../../search/search.module';
+import { UsersService } from '../../users/users.service';
+import { structureDto } from '../dto/structure.dto';
+import { Structure } from '../schemas/structure.schema';
+import { StructuresSearchService } from './structures-search.service';
+import { StructuresService } from './structures.service';
+describe('StructuresService', () => {
+  let service: StructuresService;
+
+  const mockStructureModel = {
+    create: jest.fn(),
+    deleteOne: jest.fn(),
+    countDocuments: jest.fn(),
+    findOne: jest.fn(),
+    exec: jest.fn(),
+    find: jest.fn(),
+  };
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [HttpModule, MailerModule, SearchModule, ConfigModule],
+      providers: [
+        StructuresService,
+        ConfigurationService,
+        StructuresSearchService,
+        {
+          provide: getModelToken(Structure.name),
+          useValue: mockStructureModel,
+        },
+        {
+          provide: UsersService,
+          useClass: UsersServiceMock,
+        },
+      ],
+    }).compile();
+
+    service = module.get<StructuresService>(StructuresService);
+  });
+
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+
+  it('should Initiate structure', () => {
+    const res = service.initiateStructureIndex();
+    expect(res).toBeTruthy();
+  });
+
+  it('should searchForStructures', () => {
+    let res = service.searchForStructures('a', [{ nbPrinters: '1' }]);
+    expect(res).toBeTruthy();
+    res = service.searchForStructures('a');
+    expect(res).toBeTruthy();
+  });
+
+  it('should create structure', () => {
+    const structure = new structureDto();
+    let res = service.create(null, structure);
+    expect(res).toBeTruthy();
+    res = service.create('tsfsf6296', structure);
+    expect(res).toBeTruthy();
+  });
+
+  it('should search structure', () => {
+    const filters = [{ nbPrinters: '1' }];
+    let res = service.search('', filters);
+    expect(res).toBeTruthy();
+    res = service.search(null, filters);
+    expect(res).toBeTruthy();
+    res = service.search(null);
+    expect(res).toBeTruthy();
+  });
+
+  it('should find all structures', () => {
+    const res = service.findAll();
+    expect(res).toBeTruthy();
+  });
+
+  it('should find all unclaimed structures', () => {
+    const res = service.findAllUnclaimed();
+    expect(res).toBeTruthy();
+  });
+
+  it('should find all formated structures', () => {
+    const res = service.findAllFormated(null, null, null);
+    expect(res).toBeTruthy();
+  });
+
+  it('should populate ES', () => {
+    const res = service.populateES();
+    expect(res).toBeTruthy();
+  });
+
+  it('should report structure Error', () => {
+    let res = service.reportStructureError('6093ba0e2ab5775cfc01ed3e', '');
+    expect(res).toBeTruthy();
+    res = service.reportStructureError(null, '');
+    expect(res).toBeTruthy();
+  });
+});
diff --git a/src/tcl/tclStopPoint.service.spec.ts b/src/tcl/tclStopPoint.service.spec.ts
deleted file mode 100644
index 2c6d4220f3f2a135aabaa0b0ec423dab6713a53b..0000000000000000000000000000000000000000
--- a/src/tcl/tclStopPoint.service.spec.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { HttpModule } from '@nestjs/common';
-import { getModelToken } from '@nestjs/mongoose';
-import { Test, TestingModule } from '@nestjs/testing';
-import { TclStopPoint } from './tclStopPoint.schema';
-import { TclStopPointService } from './tclStopPoint.service';
-
-describe('TclService', () => {
-  let service: TclStopPointService;
-
-  beforeEach(async () => {
-    const module: TestingModule = await Test.createTestingModule({
-      imports: [HttpModule],
-      providers: [
-        TclStopPointService,
-        {
-          provide: getModelToken('TclStopPoint'),
-          useValue: TclStopPoint,
-        },
-      ],
-    }).compile();
-
-    service = module.get<TclStopPointService>(TclStopPointService);
-  });
-
-  it('should be defined', () => {
-    expect(service).toBeDefined();
-  });
-});
diff --git a/src/temp-user/temp-user.controller.spec.ts b/src/temp-user/temp-user.controller.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9005d4c87a29559f813af9a1e7c0752fc85c1e6f
--- /dev/null
+++ b/src/temp-user/temp-user.controller.spec.ts
@@ -0,0 +1,47 @@
+import { HttpModule, HttpStatus } from '@nestjs/common';
+import { Test, TestingModule } from '@nestjs/testing';
+import { MailerModule } from '../mailer/mailer.module';
+import { TempUserController } from './temp-user.controller';
+import { TempUserService } from './temp-user.service';
+
+describe('TempUserService', () => {
+  let controller: TempUserController;
+
+  const mockTempUserService = {
+    findById: jest.fn(),
+  };
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [HttpModule, MailerModule],
+      providers: [{ provide: TempUserService, useValue: mockTempUserService }],
+      controllers: [TempUserController],
+    }).compile();
+
+    controller = module.get<TempUserController>(TempUserController);
+  });
+
+  it('should be defined', () => {
+    expect(controller).toBeDefined();
+  });
+
+  describe('getTempUser', () => {
+    it('should get temporary users', async () => {
+      const tmpUser = { email: 'test@test.com', pendingStructuresLink: [] };
+      mockTempUserService.findById.mockReturnValueOnce(tmpUser);
+      expect(await controller.getTempUser('addq651')).toEqual(tmpUser);
+    });
+    it('should throw error in cas of no users', async () => {
+      const tmpUser = null;
+      mockTempUserService.findById.mockReturnValueOnce(tmpUser);
+      try {
+        await controller.getTempUser('addq651');
+        // Fail test if above expression doesn't throw anything.
+        expect(true).toBe(false);
+      } catch (e) {
+        expect(e.message).toEqual('User does not exists');
+        expect(e.status).toEqual(HttpStatus.BAD_REQUEST);
+      }
+    });
+  });
+});
diff --git a/src/temp-user/temp-user.interface.ts b/src/temp-user/temp-user.interface.ts
index 1e0a132a1bb71e3fdd88ddc3bd5262e82e0c085e..2a4e74ff88ff5ec98d24b32178e84ac01bcb494b 100644
--- a/src/temp-user/temp-user.interface.ts
+++ b/src/temp-user/temp-user.interface.ts
@@ -1,7 +1,6 @@
 import { Document, Types } from 'mongoose';
 
 export interface ITempUser extends Document {
-  readonly _id: string;
   email: string;
-  pendingStructuresLink: Types.ObjectId[];
+  pendingStructuresLink?: Types.ObjectId[];
 }
diff --git a/src/temp-user/temp-user.schema.ts b/src/temp-user/temp-user.schema.ts
index dc70ce2ac22516550162e44b51d4d2523164aa82..3112b3112f6217e5f5ab30242257aece39726a51 100644
--- a/src/temp-user/temp-user.schema.ts
+++ b/src/temp-user/temp-user.schema.ts
@@ -9,7 +9,7 @@ export class TempUser {
   email: string;
 
   @Prop({ default: null })
-  pendingStructuresLink: Types.ObjectId[];
+  pendingStructuresLink?: Types.ObjectId[];
 }
 
 export const TempUserSchema = SchemaFactory.createForClass(TempUser);
diff --git a/src/temp-user/temp-user.service.spec.ts b/src/temp-user/temp-user.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..14c2995c97c9c3497760956e0968aa0cc7497da8
--- /dev/null
+++ b/src/temp-user/temp-user.service.spec.ts
@@ -0,0 +1,107 @@
+import { HttpModule, HttpStatus } from '@nestjs/common';
+import { getModelToken } from '@nestjs/mongoose';
+import { Test, TestingModule } from '@nestjs/testing';
+import { MailerModule } from '../mailer/mailer.module';
+import { TempUserService } from './temp-user.service';
+
+describe('TempUserService', () => {
+  let service: TempUserService;
+
+  const tempUserModelMock = {
+    create: jest.fn(),
+    findOne: jest.fn(),
+    findById: jest.fn(),
+    deleteOne: jest.fn(),
+    find: jest.fn(),
+    exec: jest.fn(),
+    updateOne: jest.fn(),
+  };
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [HttpModule, MailerModule],
+      providers: [
+        TempUserService,
+        {
+          provide: getModelToken('TempUser'),
+          useValue: tempUserModelMock,
+        },
+      ],
+    }).compile();
+
+    service = module.get<TempUserService>(TempUserService);
+  });
+
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+  describe('create', () => {
+    const tmpUser = { email: 'test@test.com', pendingStructuresLink: [] };
+    it('should not create temporary user: already exist', async () => {
+      tempUserModelMock.findOne.mockResolvedValueOnce(tmpUser);
+      try {
+        await service.create(tmpUser, 'PIMMS Framboise');
+        expect(true).toBe(false);
+      } catch (e) {
+        expect(e.message).toEqual('User already exists');
+        expect(e.status).toEqual(HttpStatus.BAD_REQUEST);
+      }
+    });
+    it('should create temporary user', async () => {
+      tempUserModelMock.findOne.mockResolvedValueOnce(null).mockResolvedValueOnce(tmpUser);
+      tempUserModelMock.create.mockResolvedValueOnce(tmpUser);
+      expect(await service.create(tmpUser, 'PIMMS Framboise')).toEqual(tmpUser);
+    });
+  });
+  it('should find one', async () => {
+    const tmpUser = { email: 'test2@test.com', pendingStructuresLink: [] };
+    tempUserModelMock.findOne.mockResolvedValueOnce(tmpUser);
+    expect(await service.findOne('test2@test.com')).toEqual(tmpUser);
+  });
+
+  it('should find one by id', async () => {
+    const tmpUser = { email: 'test2@test.com', pendingStructuresLink: [] };
+    tempUserModelMock.findById.mockResolvedValueOnce(tmpUser);
+    expect(await service.findById('5fbb92e480a5c257dc0161f0')).toEqual(tmpUser);
+  });
+
+  describe('delete', () => {
+    it('should delete a temp user', async () => {
+      const tmpUser = { email: 'test2@test.com', pendingStructuresLink: [] };
+      tempUserModelMock.findOne.mockResolvedValueOnce(tmpUser);
+      tempUserModelMock.deleteOne.mockImplementationOnce(() => {});
+      expect(await service.delete('toto@test.com')).toEqual(tmpUser);
+    });
+    it('should return an error : user does not exist', async () => {
+      tempUserModelMock.findOne.mockResolvedValueOnce(null);
+      try {
+        await service.delete('toto@test.com');
+        expect(true).toBe(false);
+      } catch (e) {
+        expect(e.message).toEqual('User does not exists');
+        expect(e.status).toEqual(HttpStatus.BAD_REQUEST);
+      }
+    });
+  });
+
+  describe('updateStructureLinked', () => {
+    it('should update structure linked', async () => {
+      const tmpUser = { email: 'test2@test.com', pendingStructuresLink: [] };
+      tempUserModelMock.find.mockReturnThis();
+      tempUserModelMock.exec.mockResolvedValueOnce([]).mockResolvedValueOnce(tmpUser);
+      tempUserModelMock.updateOne.mockReturnThis();
+      expect(await service.updateStructureLinked(tmpUser)).toEqual(tmpUser);
+    });
+    it('should not update structure linked: User already linked', async () => {
+      const tmpUser = { email: 'test2@test.com', pendingStructuresLink: [] };
+      tempUserModelMock.find.mockReturnThis();
+      tempUserModelMock.exec.mockResolvedValueOnce([tmpUser]);
+      try {
+        await service.updateStructureLinked(tmpUser);
+      } catch (e) {
+        expect(e.message).toEqual('User already linked');
+        expect(e.status).toEqual(HttpStatus.UNPROCESSABLE_ENTITY);
+      }
+    });
+  });
+});
diff --git a/src/temp-user/temp-user.service.ts b/src/temp-user/temp-user.service.ts
index f4588a4b9c199c84ea49152a2d4ad3e29630faf1..8a43832237b1555687568f84cc92b2f877858336 100644
--- a/src/temp-user/temp-user.service.ts
+++ b/src/temp-user/temp-user.service.ts
@@ -1,4 +1,4 @@
-import { HttpException, HttpService, HttpStatus, Injectable } from '@nestjs/common';
+import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
 import { InjectModel } from '@nestjs/mongoose';
 import { Model, Types } from 'mongoose';
 import { MailerService } from '../mailer/mailer.service';
@@ -10,7 +10,6 @@ import { ITempUser } from './temp-user.interface';
 @Injectable()
 export class TempUserService {
   constructor(
-    private readonly httpService: HttpService,
     private readonly mailerService: MailerService,
     @InjectModel(TempUser.name) private tempUserModel: Model<ITempUser>
   ) {}
@@ -20,27 +19,26 @@ export class TempUserService {
     if (userInDb) {
       throw new HttpException('User already exists', HttpStatus.BAD_REQUEST);
     }
-    const createUser = new this.tempUserModel(createTempUser);
+    const createUser = await this.tempUserModel.create(createTempUser);
     // Send email
     this.sendUserMail(createUser, structureName);
-    createUser.save();
-    return await this.findOne(createTempUser.email);
+    return this.findOne(createTempUser.email);
   }
 
-  public async findOne(mail: string): Promise<TempUser | undefined> {
-    return this.tempUserModel.findOne({ email: mail }).exec();
+  public async findOne(mail: string): Promise<TempUser> {
+    return this.tempUserModel.findOne({ email: mail });
   }
 
-  public async findById(id: string): Promise<TempUser | undefined> {
-    return this.tempUserModel.findById(Types.ObjectId(id)).exec();
+  public async findById(id: string): Promise<TempUser> {
+    return this.tempUserModel.findById(Types.ObjectId(id));
   }
 
   public async delete(mail: string): Promise<TempUser> {
     const userInDb = await this.findOne(mail);
     if (!userInDb) {
-      throw new HttpException('User already exists', HttpStatus.BAD_REQUEST);
+      throw new HttpException('User does not exists', HttpStatus.BAD_REQUEST);
     }
-    this.tempUserModel.deleteOne({ email: mail }).exec();
+    this.tempUserModel.deleteOne({ email: mail });
     return userInDb;
   }
 
diff --git a/src/users/guards/isStructureOwner.guard.spec.ts b/src/users/guards/isStructureOwner.guard.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a92ddcf4f77b41434d9956902f2816d87d9f5c23
--- /dev/null
+++ b/src/users/guards/isStructureOwner.guard.spec.ts
@@ -0,0 +1,103 @@
+import { Reflector } from '@nestjs/core';
+import { createMock } from '@golevelup/ts-jest';
+import { Test, TestingModule } from '@nestjs/testing';
+import { ExecutionContext } from '@nestjs/common';
+import { UserRole } from '../enum/user-role.enum';
+import { IsStructureOwnerGuard } from './isStructureOwner.guard';
+import { Types } from 'mongoose';
+
+describe('isStrructureOwner', () => {
+  let guard: IsStructureOwnerGuard;
+  let reflector: Reflector;
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [],
+      providers: [
+        IsStructureOwnerGuard,
+        {
+          provide: Reflector,
+          useValue: {
+            constructor: jest.fn(),
+            get: jest.fn(),
+          },
+        },
+      ],
+    }).compile();
+
+    guard = module.get<IsStructureOwnerGuard>(IsStructureOwnerGuard);
+    reflector = module.get<Reflector>(Reflector);
+  });
+
+  afterEach(async () => {
+    jest.clearAllMocks();
+  });
+
+  it('should be defined', () => {
+    expect(guard).toBeDefined();
+  });
+
+  it('should return true if structure is in user linked structures', async () => {
+    const context = createMock<ExecutionContext>({
+      getHandler: jest.fn(),
+      switchToHttp: jest.fn().mockReturnValueOnce({
+        getRequest: jest.fn().mockReturnValueOnce({
+          user: {
+            structuresLink: ['6001a38516b08100062e4161'],
+            structureOutdatedMailSent: [],
+            pendingStructuresLink: [],
+            newEmail: null,
+            changeEmailToken: null,
+            role: 0,
+            resetPasswordToken: null,
+            validationToken: null,
+            emailVerified: true,
+            email: 'jp@test.com',
+            name: 'Jean-Paul',
+            surname: 'DESCHAMPS',
+            phone: '06 11 11 11 11',
+          },
+          params: {
+            id: '6001a38516b08100062e4161',
+          },
+        }),
+      }),
+    });
+    const result = await guard.canActivate(context);
+
+    expect(result).toBeTruthy();
+  });
+
+  it('should return false if structure is not user linked structures', async () => {
+    jest.spyOn(reflector, 'get').mockImplementation((a: any, b: any) => []);
+    const context = createMock<ExecutionContext>({
+      getHandler: jest.fn(),
+      switchToHttp: jest.fn().mockReturnValue({
+        getRequest: jest.fn().mockReturnValue({
+          user: {
+            structuresLink: ['unIdQuiExistePasTropTrop'],
+            structureOutdatedMailSent: [],
+            pendingStructuresLink: [],
+            newEmail: null,
+            changeEmailToken: null,
+            role: UserRole.user,
+            resetPasswordToken: null,
+            validationToken: null,
+            emailVerified: true,
+            email: 'jp@test.com',
+            name: 'Jean-Paul',
+            surname: 'DESCHAMPS',
+            phone: '06 11 11 11 11',
+          },
+          params: {
+            id: '6001a38516b08100062e4161',
+          },
+        }),
+      }),
+    });
+    const result = await guard.canActivate(context);
+
+    expect(result).toBeFalsy();
+    expect(reflector.get).toBeCalled();
+  });
+});
diff --git a/src/users/guards/roles.guard.spec.ts b/src/users/guards/roles.guard.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2ef376e7c64a77fd3c15ab741758bf8f64a5c549
--- /dev/null
+++ b/src/users/guards/roles.guard.spec.ts
@@ -0,0 +1,95 @@
+import { Reflector } from '@nestjs/core';
+import { createMock } from '@golevelup/ts-jest';
+import { Test, TestingModule } from '@nestjs/testing';
+import { RolesGuard } from './roles.guard';
+import { ExecutionContext } from '@nestjs/common';
+import { UserRole } from '../enum/user-role.enum';
+
+describe('RolesGuard', () => {
+  let guard: RolesGuard;
+  let reflector: Reflector;
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [],
+      providers: [
+        RolesGuard,
+        {
+          provide: Reflector,
+          useValue: {
+            constructor: jest.fn(),
+            get: jest.fn(),
+          },
+        },
+      ],
+    }).compile();
+
+    guard = module.get<RolesGuard>(RolesGuard);
+    reflector = module.get<Reflector>(Reflector);
+  });
+
+  afterEach(async () => {
+    jest.clearAllMocks();
+  });
+
+  it('should be defined', () => {
+    expect(guard).toBeDefined();
+  });
+
+  it('should skip(return true) if the `HasRoles` decorator is not set', async () => {
+    jest.spyOn(reflector, 'get').mockImplementation((a: any, b: any) => null);
+    const context = createMock<ExecutionContext>();
+    const result = await guard.canActivate(context);
+
+    expect(result).toBeTruthy();
+    expect(reflector.get).toBeCalled();
+  });
+
+  it('should return true if the `HasRoles` decorator and role is admin', async () => {
+    jest.spyOn(reflector, 'get').mockImplementation((a: any, b: any) => ['admin']);
+    const context = createMock<ExecutionContext>({
+      getHandler: jest.fn(),
+      switchToHttp: jest.fn().mockReturnValue({
+        getRequest: jest.fn().mockReturnValue({
+          user: { role: UserRole.admin },
+        }),
+      }),
+    });
+
+    const result = await guard.canActivate(context);
+    expect(result).toBeTruthy();
+    expect(reflector.get).toBeCalled();
+  });
+
+  it('should return false if the `HasRoles` decorator is set but role is not allowed', async () => {
+    jest.spyOn(reflector, 'get').mockImplementation((a: any, b: any) => ['admin']);
+    const context = createMock<ExecutionContext>({
+      getHandler: jest.fn(),
+      switchToHttp: jest.fn().mockReturnValue({
+        getRequest: jest.fn().mockReturnValue({
+          user: { role: null },
+        }),
+      }),
+    });
+
+    const result = await guard.canActivate(context);
+    expect(result).toBeFalsy();
+    expect(reflector.get).toBeCalled();
+  });
+
+  it('should return true if the `HasRoles` decorator is and role is not allowed', async () => {
+    jest.spyOn(reflector, 'get').mockImplementation((a: any, b: any) => ['user']);
+    const context = createMock<ExecutionContext>({
+      getHandler: jest.fn(),
+      switchToHttp: jest.fn().mockReturnValue({
+        getRequest: jest.fn().mockReturnValue({
+          user: { role: UserRole.user },
+        }),
+      }),
+    });
+
+    const result = await guard.canActivate(context);
+    expect(result).toBeTruthy();
+    expect(reflector.get).toBeCalled();
+  });
+});
diff --git a/src/users/users.controller.spec.ts b/src/users/users.controller.spec.ts
index 68da5450f95300fde9828f6a2ad2d1905b738753..e65b3965aa24378b580c213e074b100d9e96d158 100644
--- a/src/users/users.controller.spec.ts
+++ b/src/users/users.controller.spec.ts
@@ -1,7 +1,6 @@
 import { HttpModule } from '@nestjs/common';
 import { getModelToken } from '@nestjs/mongoose';
 import { Test, TestingModule } from '@nestjs/testing';
-import { CategoriesModule } from '../categories/categories.module';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerService } from '../mailer/mailer.service';
 import { SearchModule } from '../search/search.module';
diff --git a/test/mock/services/newsletter.mock.service.ts b/test/mock/services/newsletter.mock.service.ts
index d7b4d640c0d9cd298961fe88a660aeebbb158b1d..6b4f0d47557ff8364078971221f44eccc0ff3405 100644
--- a/test/mock/services/newsletter.mock.service.ts
+++ b/test/mock/services/newsletter.mock.service.ts
@@ -44,7 +44,7 @@ export class NewsletterServiceMock {
     });
   }
 
-  deleteOneEmail(email: string) {
+  newsletterUnsubscribe(email: string) {
     if (email === 'test@test.com') {
       throw new HttpException('Invalid  email', HttpStatus.BAD_REQUEST);
     }