diff --git a/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.spec.ts b/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a3d293e62fa7b846ca8684ae45e809d37bbab8b7
--- /dev/null
+++ b/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.spec.ts
@@ -0,0 +1,79 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { Component, Input } from '@angular/core';
+
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { DatasetListComponent } from './dataset-list.component';
+import { DATASET_FAMILY_LIST, DATASET_LIST } from '../../../../../test-data';
+import { Dataset, DatasetFamily, Survey } from '../../../../metamodel/models';
+
+describe('[Instance][SearchMultiple][Component][Datasets] DatasetListComponent', () => {
+    @Component({ selector: 'app-datasets-by-family', template: '' })
+    class DatasetsByFamilyStubComponent {
+        @Input() datasetFamily: DatasetFamily;
+        @Input() datasetList: Dataset[];
+        @Input() surveyList: Survey[];
+        @Input() selectedDatasets: string[];
+        @Input() isAllSelected: boolean;
+        @Input() isAllUnselected: boolean;
+    }
+
+    let component: DatasetListComponent;
+    let fixture: ComponentFixture<DatasetListComponent>;
+
+    beforeEach(() => {
+        TestBed.configureTestingModule({
+            declarations: [
+                DatasetListComponent,
+                DatasetsByFamilyStubComponent
+            ],
+            imports: [TooltipModule.forRoot()]
+        });
+        fixture = TestBed.createComponent(DatasetListComponent);
+        component = fixture.componentInstance;
+    });
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('#getDatasetFamilyList() should return sorted survey list', () => {
+        component.datasetList = DATASET_LIST;
+        component.datasetFamilyList = DATASET_FAMILY_LIST;
+        const sortedDatasetFamilyList: DatasetFamily[] = component.getDatasetFamilyList();
+        expect(sortedDatasetFamilyList.length).toBe(1);
+        expect(sortedDatasetFamilyList[0].label).toBe('My first dataset family');
+    });
+
+    it('#getDatasetsByFamily() should return dataset list for the given dataset family', () => {
+        component.datasetList = DATASET_LIST;
+        const datasetList: Dataset[] = component.getDatasetsByFamily(1);
+        expect(datasetList.length).toBe(2);
+        expect(datasetList[0].name).toBe('myDataset');
+        expect(datasetList[1].name).toBe('anotherDataset');
+    });
+
+    it('#getIsAllSelected() should return true if all datasets of the given dataset family are selected', () => {
+        component.datasetList = DATASET_LIST;
+        component.selectedDatasets = ['myDataset', 'anotherDataset'];
+        expect(component.getIsAllSelected(1)).toBeTruthy();
+    });
+
+    it('#getIsAllSelected() should return false if not all datasets of the given dataset family are selected', () => {
+        component.datasetList = DATASET_LIST;
+        component.selectedDatasets = ['myDataset'];
+        expect(component.getIsAllSelected(1)).toBeFalsy();
+    });
+
+    it('#getIsAllUnselected() should return true if all datasets of the given dataset family are not selected', () => {
+        component.datasetList = DATASET_LIST;
+        component.selectedDatasets = [];
+        expect(component.getIsAllUnselected(1)).toBeTruthy();
+    });
+
+    it('#getIsAllUnselected() should return false if not all datasets of the given dataset family are not selected', () => {
+        component.datasetList = DATASET_LIST;
+        component.selectedDatasets = ['myDataset'];
+        expect(component.getIsAllUnselected(1)).toBeFalsy();
+    });
+});
diff --git a/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.ts b/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.ts
index f01569abfd679097f564b04a1563c52806e6957e..164643d464f61a837f192f0ba9efb969b0aca732 100644
--- a/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.ts
+++ b/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.ts
@@ -11,15 +11,15 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from
 
 import { Dataset, DatasetFamily, Survey } from 'src/app/metamodel/models';
 
+/**
+ * @class
+ * @classdesc Dataset list component.
+ */
 @Component({
     selector: 'app-dataset-list',
     templateUrl: 'dataset-list.component.html',
     changeDetection: ChangeDetectionStrategy.OnPush
 })
-/**
- * @class
- * @classdesc Search multiple dataset list component.
- */
 export class DatasetListComponent {
     @Input() datasetFamilyList: DatasetFamily[];
     @Input() datasetList: Dataset[];
@@ -28,9 +28,9 @@ export class DatasetListComponent {
     @Output() updateSelectedDatasets: EventEmitter<string[]> = new EventEmitter();
 
     /**
-     * Returns dataset family list sorted by display, that contains datasets with cone search enabled.
+     * Returns dataset family list that contains datasets with cone search enabled.
      *
-     * @return Family[]
+     * @return DatasetFamily[]
      */
     getDatasetFamilyList(): DatasetFamily[] {
         const familyId: number[] = [];
diff --git a/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.spec.ts b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9f29194b0cbc7f35acc8ce20ee0fdea9b1791745
--- /dev/null
+++ b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.spec.ts
@@ -0,0 +1,69 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { DatasetsByFamilyComponent } from './datasets-by-family.component';
+import { DATASET_LIST, SURVEY_LIST } from '../../../../../test-data';
+
+describe('[Instance][SearchMultiple][Component][Datasets] DatasetsByFamilyComponent', () => {
+    let component: DatasetsByFamilyComponent;
+    let fixture: ComponentFixture<DatasetsByFamilyComponent>;
+
+    beforeEach(() => {
+        TestBed.configureTestingModule({
+            declarations: [DatasetsByFamilyComponent],
+            imports: [TooltipModule.forRoot()]
+        });
+        fixture = TestBed.createComponent(DatasetsByFamilyComponent);
+        component = fixture.componentInstance;
+    });
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('#isSelected() should return true if the given dataset is selected', () => {
+        component.selectedDatasets = ['toto'];
+        expect(component.isSelected('toto')).toBeTruthy();
+    });
+
+    it('#isSelected() should return false if the given dataset is not selected', () => {
+        component.selectedDatasets = [];
+        expect(component.isSelected('toto')).toBeFalsy();
+    });
+
+    it('#toggleSelection() should remove the given dataset from selectedDatasets and raise updateSelectedDatasets event', () => {
+        component.selectedDatasets = ['toto'];
+        const expectedSelectedDatasets = [];
+        component.updateSelectedDatasets.subscribe((event: string[]) => expect(event).toEqual(expectedSelectedDatasets));
+        component.toggleSelection('toto');
+    });
+
+    it('#toggleSelection() should add the given dataset to selectedDatasets and raise updateSelectedDatasets event', () => {
+        component.selectedDatasets = [];
+        const expectedSelectedDatasets = ['toto'];
+        component.updateSelectedDatasets.subscribe((event: string[]) => expect(event).toEqual(expectedSelectedDatasets));
+        component.toggleSelection('toto');
+    });
+
+    it('#selectAll() should add all datasets to selectedDatasets and raise updateSelectedDatasets event', () => {
+        component.datasetList = DATASET_LIST.filter(d => d.id_dataset_family === 1);
+        component.selectedDatasets = [];
+        const expectedSelectedDatasets = ['myDataset', 'anotherDataset'];
+        component.updateSelectedDatasets.subscribe((event: string[]) => expect(event).toEqual(expectedSelectedDatasets));
+        component.selectAll();
+    });
+
+    it('#unselectAll() should remove all datasets to selectedDatasets and raise updateSelectedDatasets event', () => {
+        component.datasetList = DATASET_LIST.filter(d => d.id_dataset_family === 1);
+        component.selectedDatasets = ['myDataset', 'anotherDataset'];
+        const expectedSelectedDatasets = [];
+        component.updateSelectedDatasets.subscribe((event: string[]) => expect(event).toEqual(expectedSelectedDatasets));
+        component.unselectAll();
+    });
+
+    it('#getSurveyDescription() should return the description of the given survey', () => {
+        component.surveyList = SURVEY_LIST;
+        expect(component.getSurveyDescription('survey-one')).toEqual('This is the description of first survey');
+    });
+});
diff --git a/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.ts b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.ts
index 8a1a260c5e72f0f86b46ee6910c9e76f1bfe5976..85cb44b08f04300feebeaf717f9593d1c167f857 100644
--- a/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.ts
+++ b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.ts
@@ -11,6 +11,10 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEn
 
 import { Dataset, DatasetFamily, Survey } from 'src/app/metamodel/models';
 
+/**
+ * @class
+ * @classdesc Datasets by family component.
+ */
 @Component({
     selector: 'app-datasets-by-family',
     templateUrl: 'datasets-by-family.component.html',
@@ -18,10 +22,6 @@ import { Dataset, DatasetFamily, Survey } from 'src/app/metamodel/models';
     changeDetection: ChangeDetectionStrategy.OnPush,
     encapsulation: ViewEncapsulation.None
 })
-/**
- * @class
- * @classdesc Search multiple datasets by family component.
- */
 export class DatasetsByFamilyComponent {
     @Input() datasetFamily: DatasetFamily;
     @Input() datasetList: Dataset[];
diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a86e34f952555f07fd597b550583aadb210a5313
--- /dev/null
+++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts
@@ -0,0 +1,54 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ProgressBarMultipleComponent } from './progress-bar-multiple.component';
+import { INSTANCE } from '../../../../test-data';
+
+describe('[Instance][SearchMultiple][Component] ProgressBarMultipleComponent', () => {
+    let component: ProgressBarMultipleComponent;
+    let fixture: ComponentFixture<ProgressBarMultipleComponent>;
+
+    beforeEach(() => {
+        TestBed.configureTestingModule({
+            declarations: [ProgressBarMultipleComponent],
+            imports: [RouterTestingModule]
+        });
+        fixture = TestBed.createComponent(ProgressBarMultipleComponent);
+        component = fixture.componentInstance;
+    });
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('#getStepClass() should return correct step class', () => {
+        let style = component.getStepClass();
+        expect(style).toBe('positionStep');
+        component.currentStep = 'position';
+        style = component.getStepClass();
+        expect(style).toBe('positionStep');
+        component.currentStep = 'datasets';
+        style = component.getStepClass();
+        expect(style).toBe('datasetsStep');
+        component.currentStep = 'result';
+        style = component.getStepClass();
+        expect(style).toBe('resultStep');
+    });
+
+    it('#getNavItemAStyle() should return correct style for navigation link', () => {
+        component.currentStep = 'step';
+        component.instance = INSTANCE;
+        expect(component.getNavItemAStyle('', false)).toBeNull();
+        expect(component.getNavItemAStyle('step', true)).toEqual({ color: 'green' });
+    });
+
+    it('#getNavItemIconCircleStyle() should return correct style for icon circle', () => {
+        component.currentStep = 'step';
+        component.instance = INSTANCE;
+        expect(component.getNavItemIconCircleStyle('', false)).toEqual({ });
+        const expectedWithStep = { 'border-color': 'green', 'background-color': 'green' };
+        expect(component.getNavItemIconCircleStyle('step', false)).toEqual(expectedWithStep);
+        const expectedWithChecked = { 'border-color': 'green', 'color': 'green' };
+        expect(component.getNavItemIconCircleStyle('', true)).toEqual(expectedWithChecked);
+    });
+});
diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts
index ece4925478828db29a2a9df8e097e3287ca2900e..0fbeafa0d654dac7fc133ccde1ee597140fbc43a 100644
--- a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts
+++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts
@@ -12,16 +12,16 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
 import { Instance } from 'src/app/metamodel/models';
 import { ConeSearch, SearchMultipleQueryParams } from 'src/app/instance/store/models';
 
+/**
+ * @class
+ * @classdesc Progress bar multiple component.
+ */
 @Component({
     selector: 'app-progress-bar-multiple',
     templateUrl: 'progress-bar-multiple.component.html',
     styleUrls: ['progress-bar-multiple.component.scss'],
     changeDetection: ChangeDetectionStrategy.OnPush
 })
-/**
- * @class
- * @classdesc Search multiple progress bar component.
- */
 export class ProgressBarMultipleComponent {
     @Input() instance: Instance;
     @Input() currentStep: string;
@@ -50,17 +50,30 @@ export class ProgressBarMultipleComponent {
         }
     }
 
-    getNavItemAStyle(currentStep: string, checked: boolean) {
+    /**
+     * Returns navigation link style.
+     *
+     * @param  {string} currentStep - The current step.
+     * @param  {boolean} checked - The checked status of current step.
+     *
+     * @return { color: string } | null
+     */
+    getNavItemAStyle(currentStep: string, checked: boolean): { color: string } | null {
         if (this.currentStep === currentStep || checked) {
-            return {
-                'color': this.instance.config.design.design_color
-            }
-        } else {
-            return null;
+            return { 'color': this.instance.config.design.design_color }
         }
+        return null;
     }
 
-    getNavItemIconCircleStyle(currentStep: string, checked: boolean) {
+    /**
+     * Returns navigation icon circle style.
+     *
+     * @param  {string} currentStep - The current step.
+     * @param  {boolean} checked - The checked status of current step.
+     *
+     * @return any
+     */
+    getNavItemIconCircleStyle(currentStep: string, checked: boolean): any {
         let style = {};
         if (this.currentStep === currentStep) {
             style['border-color'] = this.instance.config.design.design_color;
diff --git a/client/src/app/instance/search-multiple/components/result/overview.component.spec.ts b/client/src/app/instance/search-multiple/components/result/overview.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..68532aaec60f06a8f61abcca51d232d1e4ab345b
--- /dev/null
+++ b/client/src/app/instance/search-multiple/components/result/overview.component.spec.ts
@@ -0,0 +1,60 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { OverviewComponent } from './overview.component';
+import { Dataset, DatasetFamily } from '../../../../metamodel/models';
+import { DATASET_FAMILY_LIST, DATASET_LIST } from '../../../../../test-data';
+
+describe('[Instance][SearchMultiple][Component][Result] OverviewComponent', () => {
+    let component: OverviewComponent;
+    let fixture: ComponentFixture<OverviewComponent>;
+
+    beforeEach(() => {
+        TestBed.configureTestingModule({
+            declarations: [OverviewComponent],
+            imports: [RouterTestingModule]
+        });
+        fixture = TestBed.createComponent(OverviewComponent);
+        component = fixture.componentInstance;
+    });
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('#getTotalObject() should return the sum of results for each dataset', () => {
+        component.dataLength = [{ datasetName: 'firstDataset', length: 1 }, { datasetName: 'secondDataset', length: 1 }];
+        expect(component.getTotalObject()).toEqual(2);
+    });
+
+    it('#getTotalDatasets() should return count datasets with results', () => {
+        component.dataLength = [{ datasetName: 'firstDataset', length: 1 }, { datasetName: 'secondDataset', length: 1 }];
+        expect(component.getTotalDatasets()).toEqual(2);
+    });
+
+    it('#getSortedDatasetFamilyList() should return sorted dataset family list with selected datasets in it', () => {
+        component.selectedDatasets = ['myDataset', 'anotherDataset'];
+        component.datasetList = DATASET_LIST;
+        component.datasetFamilyList = DATASET_FAMILY_LIST;
+        const sortedDatasetFamilyList: DatasetFamily[] = component.getSortedDatasetFamilyList();
+        expect(sortedDatasetFamilyList.length).toEqual(1);
+        expect(sortedDatasetFamilyList[0].label).toBe('My first dataset family');
+    });
+
+    it('#getSelectedDatasetsByFamily() should return selected dataset that belongs to the given dataset family', () => {
+        component.selectedDatasets = ['myDataset'];
+        component.datasetList = DATASET_LIST;
+        const selectedDatasets: Dataset[] = component.getSelectedDatasetsByFamily(1);
+        expect(selectedDatasets.length).toEqual(1);
+    });
+
+    it('#getCountByDataset() should return count for the given dataset', () => {
+        component.dataLength = [{ datasetName: 'firstDataset', length: 1 }, { datasetName: 'secondDataset', length: 2 }];
+        expect(component.getCountByDataset('firstDataset')).toEqual(1);
+    });
+
+    it('#getCsQueryParams() should return cone search query parameters', () => {
+        component.coneSearch = { ra: 1, dec: 2, radius: 3 };
+        expect(component.getCsQueryParams()).toEqual({ cs: '1:2:3' });
+    });
+});
diff --git a/client/src/app/instance/search-multiple/components/result/overview.component.ts b/client/src/app/instance/search-multiple/components/result/overview.component.ts
index e85af4d2feed7f641e352c6f5a998a7a596899c8..25fc216d76b3bebd419f902d9044c8366502d70d 100644
--- a/client/src/app/instance/search-multiple/components/result/overview.component.ts
+++ b/client/src/app/instance/search-multiple/components/result/overview.component.ts
@@ -12,6 +12,10 @@ import { Component, Input } from '@angular/core';
 import { DatasetFamily, Dataset } from 'src/app/metamodel/models';
 import { ConeSearch, SearchMultipleDatasetLength, SearchMultipleQueryParams } from 'src/app/instance/store/models';
 
+/**
+ * @class
+ * @classdesc Overview component.
+ */
 @Component({
     selector: 'app-overview',
     templateUrl: 'overview.component.html'
@@ -37,7 +41,7 @@ export class OverviewComponent {
     }
 
     /**
-     * Returns total number of datasets with results.
+     * Returns count of datasets with results.
      *
      * @return number
      */
@@ -46,9 +50,9 @@ export class OverviewComponent {
     }
 
     /**
-     * Returns dataset families sorted by display, that contains selected datasets.
+     * Returns dataset families that contains selected datasets.
      *
-     * @return Family[]
+     * @return DatasetFamily[]
      */
     getSortedDatasetFamilyList(): DatasetFamily[] {
         let datasetFamiliesWithSelectedDataset: DatasetFamily[] = [];
@@ -76,7 +80,7 @@ export class OverviewComponent {
     }
 
     /**
-     * Returns the result number for the given dataset name.
+     * Returns the result count for the given dataset name.
      *
      * @param  {string} dname - The dataset name.
      *
@@ -86,9 +90,12 @@ export class OverviewComponent {
         return this.dataLength.find(datasetLength => datasetLength.datasetName === dname).length;
     }
 
-    getCsQueryParams() {
-        return {
-            cs: `${this.coneSearch.ra}:${this.coneSearch.dec}:${this.coneSearch.radius}`
-        }
+    /**
+     * Returns the cone search query parameters.
+     *
+     * @return { cs: string }
+     */
+    getCsQueryParams(): { cs: string } {
+        return { cs: `${this.coneSearch.ra}:${this.coneSearch.dec}:${this.coneSearch.radius}` }
     }
 }
diff --git a/client/src/app/instance/search-multiple/components/summary-multiple.component.spec.ts b/client/src/app/instance/search-multiple/components/summary-multiple.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..37133619d27c1201b33d16de6774f0e9243e0cb2
--- /dev/null
+++ b/client/src/app/instance/search-multiple/components/summary-multiple.component.spec.ts
@@ -0,0 +1,43 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+
+import { AccordionModule } from 'ngx-bootstrap/accordion';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { SummaryMultipleComponent } from './summary-multiple.component';
+import { DATASET, DATASET_FAMILY_LIST, DATASET_LIST } from '../../../../test-data';
+
+describe('[Instance][SearchMultiple][Component] SummaryMultipleComponent', () => {
+    let component: SummaryMultipleComponent;
+    let fixture: ComponentFixture<SummaryMultipleComponent>;
+
+    beforeEach(() => {
+        TestBed.configureTestingModule({
+            declarations: [SummaryMultipleComponent],
+            imports: [
+                AccordionModule.forRoot(),
+                TooltipModule.forRoot(),
+                BrowserAnimationsModule
+            ]
+        });
+        fixture = TestBed.createComponent(SummaryMultipleComponent);
+        component = fixture.componentInstance;
+    });
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('#getDatasetFamilyList() should return list of dataset families that contains datasets with cone search enabled', () => {
+        component.datasetFamilyList = DATASET_FAMILY_LIST;
+        component.datasetList = [DATASET];
+        expect(component.getDatasetFamilyList()[0].label).toBe('My first dataset family');
+    });
+
+    it('#getSelectedDatasetsByFamily() should return list of selected datasets for the given dataset family', () => {
+        component.datasetList = DATASET_LIST;
+        component.selectedDatasets = ['myDataset'];
+        expect(component.getSelectedDatasetsByFamily(1).length).toEqual(1);
+        expect(component.getSelectedDatasetsByFamily(1)[0].name).toEqual('myDataset');
+    });
+});
diff --git a/client/src/app/instance/search-multiple/components/summary-multiple.component.ts b/client/src/app/instance/search-multiple/components/summary-multiple.component.ts
index 790fcd5c75c8862f0dab3bef3ff867edc4c7a361..fb6900bee9918b8a0ff344e25a881f3b67224841 100644
--- a/client/src/app/instance/search-multiple/components/summary-multiple.component.ts
+++ b/client/src/app/instance/search-multiple/components/summary-multiple.component.ts
@@ -12,16 +12,16 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
 import { SearchMultipleQueryParams, ConeSearch } from 'src/app/instance/store/models';
 import { Dataset, DatasetFamily } from 'src/app/metamodel/models';
 
+/**
+ * @class
+ * @classdesc Summary multiple component.
+ */
 @Component({
     selector: 'app-summary-multiple',
     templateUrl: 'summary-multiple.component.html',
     styleUrls: ['summary-multiple.component.scss'],
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
-/**
- * @class
- * @classdesc Search multiple summary component.
- */
 export class SummaryMultipleComponent {
     @Input() currentStep: string;
     @Input() coneSearch: ConeSearch;
@@ -33,7 +33,7 @@ export class SummaryMultipleComponent {
     accordionFamilyIsOpen = true;
 
     /**
-     * Returns dataset families sorted by display, that contains datasets with cone search enabled.
+     * Returns dataset families that contains datasets with cone search enabled.
      *
      * @return Family[]
      */
@@ -44,9 +44,7 @@ export class SummaryMultipleComponent {
                 familiesId.push(d.id_dataset_family);
             }
         });
-        return this.datasetFamilyList
-            .filter(f => familiesId.includes(f.id))
-            //.sort(sortByDisplay);
+        return this.datasetFamilyList.filter(f => familiesId.includes(f.id));
     }
 
     /**
diff --git a/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.spec.ts b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..69b64e6f6f803b12951d53d835f5593d15e3ea8f
--- /dev/null
+++ b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.spec.ts
@@ -0,0 +1,61 @@
+import { Component } from '@angular/core';
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { MockStore, provideMockStore } from '@ngrx/store/testing';
+import { of } from 'rxjs';
+
+import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component';
+import * as searchActions from '../../store/actions/search.actions';
+import * as searchMultipleActions from '../../store/actions/search-multiple.actions';
+
+describe('[Instance][SearchMultiple][Container] AbstractSearchComponent', () => {
+    @Component({
+        selector: 'app-fake',
+        template: ''
+    })
+    class MyFakeComponent extends AbstractSearchMultipleComponent {
+        ngOnInit() {
+            super.ngOnInit();
+        }
+
+        ngOnDestroy() {
+            super.ngOnDestroy();
+        }
+    }
+
+    let component: MyFakeComponent;
+    let fixture: ComponentFixture<MyFakeComponent>;
+    let store: MockStore;
+
+    beforeEach(waitForAsync(() => {
+        TestBed.configureTestingModule({
+            declarations: [MyFakeComponent],
+            providers: [provideMockStore({ })]
+        });
+        fixture = TestBed.createComponent(MyFakeComponent);
+        component = fixture.componentInstance;
+        store = TestBed.inject(MockStore);
+    }));
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('should execute ngOnInit lifecycle', (done) => {
+        component.datasetListIsLoaded = of(true);
+        const spy = jest.spyOn(store, 'dispatch');
+        component.ngOnInit();
+        Promise.resolve(null).then(function() {
+            expect(spy).toHaveBeenCalledTimes(1);
+            expect(spy).toHaveBeenCalledWith(searchMultipleActions.initSearch());
+            done();
+        });
+    });
+
+    it('#ngOnDestroy() should unsubscribe from datasetListSubscription', () => {
+        component.datasetListSubscription = of().subscribe();
+        const spy = jest.spyOn(component.datasetListSubscription, 'unsubscribe');
+        component.ngOnDestroy();
+        expect(spy).toHaveBeenCalledTimes(1);
+    });
+});
diff --git a/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts
index d8bbadd476b404c8b20a43d728284d0423c3a67f..9636c26a182b8dda539f9f069a5c25344680312e 100644
--- a/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts
+++ b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts
@@ -12,6 +12,14 @@ import * as searchMultipleActions from '../../store/actions/search-multiple.acti
 import * as searchMultipleSelector from 'src/app/instance/store/selectors/search-multiple.selector';
 import * as coneSearchSelector from 'src/app/instance/store/selectors/cone-search.selector';
 
+/**
+ * @abstract
+ * @class
+ * @classdesc Abstract search multiple container.
+ *
+ * @implements OnInit
+ * @implements OnDestroy
+ */
 @Directive()
 export abstract class AbstractSearchMultipleComponent implements OnInit, OnDestroy {
     public pristine: Observable<boolean>;
@@ -26,8 +34,7 @@ export abstract class AbstractSearchMultipleComponent implements OnInit, OnDestr
     public selectedDatasets: Observable<string[]>;
     public coneSearch: Observable<ConeSearch>;
     public queryParams: Observable<SearchMultipleQueryParams>;
-
-    private datasetListSubscription: Subscription;
+    public datasetListSubscription: Subscription;
 
     constructor(protected store: Store<{ }>) {
         this.pristine = this.store.select(searchMultipleSelector.selectPristine);
@@ -43,16 +50,18 @@ export abstract class AbstractSearchMultipleComponent implements OnInit, OnDestr
         this.coneSearch = this.store.select(coneSearchSelector.selectConeSearch);
         this.queryParams = this.store.select(searchMultipleSelector.selectQueryParams);
     }
-    
-    ngOnInit() {
+
+    ngOnInit(): void {
         this.datasetListSubscription = this.datasetListIsLoaded.subscribe(datasetListIsLoaded =>  {
             if (datasetListIsLoaded) {
+                // Create a micro task that is processed after the current synchronous code
+                // This micro task prevent the expression has changed after view init error
                 Promise.resolve(null).then(() => this.store.dispatch(searchMultipleActions.initSearch()));
             }
         })
     }
 
-    ngOnDestroy() {
-        this.datasetListSubscription.unsubscribe();
+    ngOnDestroy(): void {
+        if (this.datasetListSubscription) this.datasetListSubscription.unsubscribe();
     }
 }
diff --git a/client/src/app/instance/search-multiple/containers/datasets.component.spec.ts b/client/src/app/instance/search-multiple/containers/datasets.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5ca7160f495214a2dd58fd3a76618747c0582bbc
--- /dev/null
+++ b/client/src/app/instance/search-multiple/containers/datasets.component.spec.ts
@@ -0,0 +1,78 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { Component, Input } from '@angular/core';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { MockStore, provideMockStore } from '@ngrx/store/testing';
+
+import { DatasetsComponent } from './datasets.component';
+import { Dataset, DatasetFamily, Survey } from '../../../metamodel/models';
+import { ConeSearch, SearchMultipleQueryParams } from '../../store/models';
+import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component';
+import * as searchMultipleActions from '../../store/actions/search-multiple.actions';
+
+describe('[Instance][SearchMultiple][Container] DatasetsComponent', () => {
+    @Component({ selector: 'app-spinner', template: '' })
+    class SpinnerStubComponent { }
+
+    @Component({ selector: 'app-dataset-list', template: '' })
+    class DatasetListStubComponent {
+        @Input() datasetFamilyList: DatasetFamily[];
+        @Input() datasetList: Dataset[];
+        @Input() surveyList: Survey[];
+        @Input() selectedDatasets: string[];
+    }
+
+    @Component({ selector: 'app-summary-multiple', template: '' })
+    class SummaryMultipleStubComponent {
+        @Input() currentStep: string;
+        @Input() coneSearch: ConeSearch;
+        @Input() selectedDatasets: string[];
+        @Input() queryParams: SearchMultipleQueryParams;
+        @Input() datasetFamilyList: DatasetFamily[];
+        @Input() datasetList: Dataset[];
+    }
+
+    let component: DatasetsComponent;
+    let fixture: ComponentFixture<DatasetsComponent>;
+    let store: MockStore;
+
+    beforeEach(waitForAsync(() => {
+        TestBed.configureTestingModule({
+            imports: [RouterTestingModule],
+            declarations: [
+                DatasetsComponent,
+                SpinnerStubComponent,
+                DatasetListStubComponent,
+                SummaryMultipleStubComponent
+            ],
+            providers: [provideMockStore({ })]
+        });
+        fixture = TestBed.createComponent(DatasetsComponent);
+        component = fixture.componentInstance;
+        store = TestBed.inject(MockStore);
+    }));
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('should execute ngOnInit lifecycle', (done) => {
+        const spy = jest.spyOn(store, 'dispatch');
+        jest.spyOn(AbstractSearchMultipleComponent.prototype, 'ngOnInit').mockReturnThis();
+        component.ngOnInit();
+        Promise.resolve(null).then(function() {
+            expect(spy).toHaveBeenCalledTimes(2);
+            expect(spy).toHaveBeenCalledWith(searchMultipleActions.changeStep({ step: 'datasets' }));
+            expect(spy).toHaveBeenCalledWith(searchMultipleActions.checkDatasets());
+            done();
+        });
+    });
+
+    it('#updateSelectedDatasets() should dispatch updateSelectedDatasets action', () => {
+        const selectedDatasets: string[] = ['myDataset', 'myOtherDataset'];
+        const spy = jest.spyOn(store, 'dispatch');
+        component.updateSelectedDatasets(selectedDatasets);
+        expect(spy).toHaveBeenCalledTimes(1);
+        expect(spy).toHaveBeenCalledWith(searchMultipleActions.updateSelectedDatasets({ selectedDatasets }));
+    });
+});
diff --git a/client/src/app/instance/search-multiple/containers/datasets.component.ts b/client/src/app/instance/search-multiple/containers/datasets.component.ts
index 5b990465122fc275552cdd57367d0299df39bccc..816fa7c6601cd00d3af5545b559b6e2fdaaf5870 100644
--- a/client/src/app/instance/search-multiple/containers/datasets.component.ts
+++ b/client/src/app/instance/search-multiple/containers/datasets.component.ts
@@ -7,7 +7,7 @@
  * file that was distributed with this source code.
  */
 
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 
 import { Store } from '@ngrx/store';
 import { Observable } from 'rxjs';
@@ -17,11 +17,18 @@ import { AbstractSearchMultipleComponent } from './abstract-search-multiple.comp
 import * as searchMultipleActions from '../../store/actions/search-multiple.actions';
 import * as surveySelector from 'src/app/metamodel/selectors/survey.selector';
 
+/**
+ * @class
+ * @classdesc Datasets container.
+ *
+ * @extends AbstractSearchMultipleComponent
+ * @implements OnInit
+ */
 @Component({
     selector: 'app-datasets',
     templateUrl: 'datasets.component.html'
 })
-export class DatasetsComponent extends AbstractSearchMultipleComponent {
+export class DatasetsComponent extends AbstractSearchMultipleComponent implements OnInit {
     public surveyListIsLoading: Observable<boolean>;
     public surveyListIsLoaded: Observable<boolean>;
     public surveyList: Observable<Survey[]>;
@@ -33,13 +40,20 @@ export class DatasetsComponent extends AbstractSearchMultipleComponent {
         this.surveyList = store.select(surveySelector.selectAllSurveys);
     }
 
-    ngOnInit() {
+    ngOnInit(): void {
+        // Create a micro task that is processed after the current synchronous code
+        // This micro task prevent the expression has changed after view init error
         Promise.resolve(null).then(() => this.store.dispatch(searchMultipleActions.changeStep({ step: 'datasets' })));
         Promise.resolve(null).then(() => this.store.dispatch(searchMultipleActions.checkDatasets()));
         super.ngOnInit();
     }
 
-    updateSelectedDatasets(selectedDatasets: string[]) {
+    /**
+     * Dispatches action to update selected datasets.
+     *
+     * @param  {string[]} selectedDatasets - The selected datasets.
+     */
+    updateSelectedDatasets(selectedDatasets: string[]): void {
         this.store.dispatch(searchMultipleActions.updateSelectedDatasets({ selectedDatasets }));
     }
 }
diff --git a/client/src/app/instance/search-multiple/containers/position.component.spec.ts b/client/src/app/instance/search-multiple/containers/position.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..84a0914057bb7b80650f61a4919096a35bd27f54
--- /dev/null
+++ b/client/src/app/instance/search-multiple/containers/position.component.spec.ts
@@ -0,0 +1,92 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { Component, Input } from '@angular/core';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { MockStore, provideMockStore } from '@ngrx/store/testing';
+
+import { PositionComponent } from './position.component';
+import { Dataset, DatasetFamily } from '../../../metamodel/models';
+import { ConeSearch, Resolver, SearchMultipleQueryParams } from '../../store/models';
+import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component';
+import * as searchMultipleActions from '../../store/actions/search-multiple.actions';
+import * as coneSearchActions from '../../store/actions/cone-search.actions';
+
+describe('[Instance][SearchMultiple][Container] PositionComponent', () => {
+    @Component({ selector: 'app-spinner', template: '' })
+    class SpinnerStubComponent { }
+
+    @Component({ selector: 'app-cone-search', template: '' })
+    class ConeSearchStubComponent {
+        @Input() coneSearch: ConeSearch;
+        @Input() resolver: Resolver;
+        @Input() resolverIsLoading: boolean;
+        @Input() resolverIsLoaded: boolean;
+    }
+
+    @Component({ selector: 'app-summary-multiple', template: '' })
+    class SummaryMultipleStubComponent {
+        @Input() currentStep: string;
+        @Input() coneSearch: ConeSearch;
+        @Input() selectedDatasets: string[];
+        @Input() queryParams: SearchMultipleQueryParams;
+        @Input() datasetFamilyList: DatasetFamily[];
+        @Input() datasetList: Dataset[];
+    }
+
+    let component: PositionComponent;
+    let fixture: ComponentFixture<PositionComponent>;
+    let store: MockStore;
+
+    beforeEach(waitForAsync(() => {
+        TestBed.configureTestingModule({
+            imports: [RouterTestingModule],
+            declarations: [
+                PositionComponent,
+                SpinnerStubComponent,
+                ConeSearchStubComponent,
+                SummaryMultipleStubComponent
+            ],
+            providers: [provideMockStore({ })]
+        });
+        fixture = TestBed.createComponent(PositionComponent);
+        component = fixture.componentInstance;
+        store = TestBed.inject(MockStore);
+    }));
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('should execute ngOnInit lifecycle', (done) => {
+        const spy = jest.spyOn(store, 'dispatch');
+        jest.spyOn(AbstractSearchMultipleComponent.prototype, 'ngOnInit').mockReturnThis();
+        component.ngOnInit();
+        Promise.resolve(null).then(function() {
+            expect(spy).toHaveBeenCalledTimes(1);
+            expect(spy).toHaveBeenCalledWith(searchMultipleActions.changeStep({ step: 'position' }));
+            done();
+        });
+    });
+
+    it('#addConeSearch() should dispatch addConeSearch action', () => {
+        const coneSearch: ConeSearch = { ra: 1, dec: 2, radius: 3 };
+        const spy = jest.spyOn(store, 'dispatch');
+        component.addConeSearch(coneSearch);
+        expect(spy).toHaveBeenCalledTimes(1);
+        expect(spy).toHaveBeenCalledWith(coneSearchActions.addConeSearch({ coneSearch }));
+    });
+
+    it('#deleteConeSearch() should dispatch deleteConeSearch action', () => {
+        const spy = jest.spyOn(store, 'dispatch');
+        component.deleteConeSearch();
+        expect(spy).toHaveBeenCalledTimes(1);
+        expect(spy).toHaveBeenCalledWith(coneSearchActions.deleteConeSearch());
+    });
+
+    it('#retrieveCoordinates() should dispatch retrieveCoordinates action', () => {
+        const spy = jest.spyOn(store, 'dispatch');
+        component.retrieveCoordinates('toto');
+        expect(spy).toHaveBeenCalledTimes(1);
+        expect(spy).toHaveBeenCalledWith(coneSearchActions.retrieveCoordinates({ name: 'toto' }));
+    });
+});
diff --git a/client/src/app/instance/search-multiple/containers/position.component.ts b/client/src/app/instance/search-multiple/containers/position.component.ts
index dea597950d3f0c527909d7059537152eda0c00f8..a56e99ce0021ad9d2162bda673db692ca65f53e7 100644
--- a/client/src/app/instance/search-multiple/containers/position.component.ts
+++ b/client/src/app/instance/search-multiple/containers/position.component.ts
@@ -7,7 +7,7 @@
  * file that was distributed with this source code.
  */
 
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 
 import { Store } from '@ngrx/store';
 import { Observable } from 'rxjs';
@@ -18,11 +18,18 @@ import * as searchMultipleActions from '../../store/actions/search-multiple.acti
 import * as coneSearchActions from '../../store/actions/cone-search.actions';
 import * as coneSearchSelector from '../../store/selectors/cone-search.selector';
 
+/**
+ * @class
+ * @classdesc Position container.
+ *
+ * @extends AbstractSearchMultipleComponent
+ * @implements OnInit
+ */
 @Component({
     selector: 'app-position',
     templateUrl: 'position.component.html'
 })
-export class PositionComponent extends AbstractSearchMultipleComponent {
+export class PositionComponent extends AbstractSearchMultipleComponent implements OnInit {
     public resolver: Observable<Resolver>;
     public resolverIsLoading: Observable<boolean>;
     public resolverIsLoaded: Observable<boolean>;
@@ -34,19 +41,34 @@ export class PositionComponent extends AbstractSearchMultipleComponent {
         this.resolverIsLoaded = this.store.select(coneSearchSelector.selectResolverIsLoaded);
     }
 
-    ngOnInit() {
+    ngOnInit(): void {
+        // Create a micro task that is processed after the current synchronous code
+        // This micro task prevent the expression has changed after view init error
         Promise.resolve(null).then(() => this.store.dispatch(searchMultipleActions.changeStep({ step: 'position' })));
         super.ngOnInit();
     }
 
+    /**
+     * Dispatches action to add the given cone search.
+     *
+     * @param  {ConeSearch} coneSearch - The cone search.
+     */
     addConeSearch(coneSearch: ConeSearch): void {
         this.store.dispatch(coneSearchActions.addConeSearch({ coneSearch }));
     }
 
+    /**
+     * Dispatches action to remove cone search.
+     */
     deleteConeSearch(): void {
         this.store.dispatch(coneSearchActions.deleteConeSearch());
     }
 
+    /**
+     * Dispatches action to retrieve coordinates of object from its name.
+     *
+     * @param  {string} name - The object name.
+     */
     retrieveCoordinates(name: string): void {
         this.store.dispatch(coneSearchActions.retrieveCoordinates({ name }));
     }
diff --git a/client/src/app/instance/search-multiple/containers/result-multiple.component.spec.ts b/client/src/app/instance/search-multiple/containers/result-multiple.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4cb2ae0c0191b4ceedd1debde6e128842952c307
--- /dev/null
+++ b/client/src/app/instance/search-multiple/containers/result-multiple.component.spec.ts
@@ -0,0 +1,74 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { Component, Input } from '@angular/core';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { MockStore, provideMockStore } from '@ngrx/store/testing';
+import { of } from 'rxjs';
+
+import { ResultMultipleComponent } from './result-multiple.component';
+import { Dataset, DatasetFamily } from '../../../metamodel/models';
+import { ConeSearch, SearchMultipleDatasetLength, SearchMultipleQueryParams } from '../../store/models';
+import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component';
+import * as searchMultipleActions from '../../store/actions/search-multiple.actions';
+
+describe('[Instance][SearchMultiple][Container] ResultMultipleComponent', () => {
+    @Component({ selector: 'app-spinner', template: '' })
+    class SpinnerStubComponent { }
+
+    @Component({ selector: 'app-overview', template: '' })
+    class OverviewStubComponent {
+        @Input() instanceSelected: string;
+        @Input() datasetFamilyList: DatasetFamily[];
+        @Input() datasetList: Dataset[];
+        @Input() coneSearch: ConeSearch;
+        @Input() selectedDatasets: string[];
+        @Input() dataLength: SearchMultipleDatasetLength[];
+        @Input() queryParams: SearchMultipleQueryParams;
+    }
+
+    let component: ResultMultipleComponent;
+    let fixture: ComponentFixture<ResultMultipleComponent>;
+    let store: MockStore;
+
+    beforeEach(waitForAsync(() => {
+        TestBed.configureTestingModule({
+            imports: [RouterTestingModule],
+            declarations: [
+                ResultMultipleComponent,
+                SpinnerStubComponent,
+                OverviewStubComponent
+            ],
+            providers: [provideMockStore({ })]
+        });
+        fixture = TestBed.createComponent(ResultMultipleComponent);
+        component = fixture.componentInstance;
+        store = TestBed.inject(MockStore);
+    }));
+
+    it('should create the component', () => {
+        expect(component).toBeTruthy();
+    });
+
+    it('should execute ngOnInit lifecycle', (done) => {
+        component.pristine = of(false);
+        const spy = jest.spyOn(store, 'dispatch');
+        jest.spyOn(AbstractSearchMultipleComponent.prototype, 'ngOnInit').mockReturnThis();
+        component.ngOnInit();
+        Promise.resolve(null).then(function() {
+            expect(spy).toHaveBeenCalledTimes(4);
+            expect(spy).toHaveBeenCalledWith(searchMultipleActions.changeStep({ step: 'result' }));
+            expect(spy).toHaveBeenCalledWith(searchMultipleActions.checkDatasets());
+            expect(spy).toHaveBeenCalledWith(searchMultipleActions.checkResult());
+            expect(spy).toHaveBeenCalledWith(searchMultipleActions.retrieveDataLength());
+            done();
+        });
+    });
+
+    it('#ngOnDestroy() should unsubscribe from pristineSubscription', () => {
+        component.pristineSubscription = of().subscribe();
+        const spy = jest.spyOn(component.pristineSubscription, 'unsubscribe');
+        jest.spyOn(AbstractSearchMultipleComponent.prototype, 'ngOnDestroy').mockReturnThis();
+        component.ngOnDestroy();
+        expect(spy).toHaveBeenCalledTimes(1);
+    });
+});
diff --git a/client/src/app/instance/search-multiple/containers/result-multiple.component.ts b/client/src/app/instance/search-multiple/containers/result-multiple.component.ts
index 3e4d66b40fbfcad6aabcededb30c6f628554f20d..cd50bfbc06ae6f0320273184cca8b1cb0fb4a733 100644
--- a/client/src/app/instance/search-multiple/containers/result-multiple.component.ts
+++ b/client/src/app/instance/search-multiple/containers/result-multiple.component.ts
@@ -7,7 +7,7 @@
  * file that was distributed with this source code.
  */
 
-import { Component } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
 
 import { Observable, Subscription } from 'rxjs';
 import { Store } from '@ngrx/store';
@@ -17,19 +17,26 @@ import { AbstractSearchMultipleComponent } from './abstract-search-multiple.comp
 import * as searchMultipleActions from '../../store/actions/search-multiple.actions';
 import * as searchMultipleSelector from 'src/app/instance/store/selectors/search-multiple.selector';
 
+/**
+ * @class
+ * @classdesc Result multiple container.
+ *
+ * @extends AbstractSearchMultipleComponent
+ * @implements OnInit
+ * @implements OnDestroy
+ */
 @Component({
     selector: 'app-result-multiple',
     templateUrl: 'result-multiple.component.html'
 })
-export class ResultMultipleComponent extends AbstractSearchMultipleComponent {
+export class ResultMultipleComponent extends AbstractSearchMultipleComponent implements OnInit, OnDestroy{
     public dataLength: Observable<SearchMultipleDatasetLength[]>;
     public dataLengthIsLoading: Observable<boolean>;
     public dataLengthIsLoaded: Observable<boolean>;
     public data: Observable<SearchMultipleDatasetData[]>;
     public dataIsLoading: Observable<boolean>;
     public dataIsLoaded: Observable<boolean>;
-
-    private pristineSubscription: Subscription;
+    public pristineSubscription: Subscription;
 
     constructor(protected store: Store<{ }>) {
         super(store);
@@ -41,7 +48,9 @@ export class ResultMultipleComponent extends AbstractSearchMultipleComponent {
         this.dataIsLoaded = this.store.select(searchMultipleSelector.selectDataIsLoaded);
     }
 
-    ngOnInit() {
+    ngOnInit(): void {
+        // Create a micro task that is processed after the current synchronous code
+        // This micro task prevent the expression has changed after view init error
         Promise.resolve(null).then(() => this.store.dispatch(searchMultipleActions.changeStep({ step: 'result' })));
         Promise.resolve(null).then(() => this.store.dispatch(searchMultipleActions.checkDatasets()));
         Promise.resolve(null).then(() => this.store.dispatch(searchMultipleActions.checkResult()));
@@ -53,8 +62,8 @@ export class ResultMultipleComponent extends AbstractSearchMultipleComponent {
         });
     }
 
-    ngOnDestroy() {
-        this.pristineSubscription.unsubscribe();
+    ngOnDestroy(): void {
+        if (this.pristineSubscription) this.pristineSubscription.unsubscribe();
         super.ngOnDestroy();
     }
 }
diff --git a/client/src/app/instance/search-multiple/search-multiple-routing.module.ts b/client/src/app/instance/search-multiple/search-multiple-routing.module.ts
index a3590eb28c7d96bbd48addb36fa15a9d00c3ff0b..7c7a014309f6bc3c9b5061493c1bb466a5d14ce7 100644
--- a/client/src/app/instance/search-multiple/search-multiple-routing.module.ts
+++ b/client/src/app/instance/search-multiple/search-multiple-routing.module.ts
@@ -26,6 +26,10 @@ const routes: Routes = [
     }
 ];
 
+/**
+ * @class
+ * @classdesc Search multiple routing module.
+ */
 @NgModule({
     imports: [RouterModule.forChild(routes)],
     exports: [RouterModule]
diff --git a/client/src/app/instance/search-multiple/search-multiple.component.spec.ts b/client/src/app/instance/search-multiple/search-multiple.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bf42abc813a72e5ee20c2cae51572f95e05f3d53
--- /dev/null
+++ b/client/src/app/instance/search-multiple/search-multiple.component.spec.ts
@@ -0,0 +1,45 @@
+import { Component, Input } from '@angular/core';
+import { TestBed, waitForAsync, ComponentFixture  } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { provideMockStore, MockStore } from '@ngrx/store/testing';
+
+import { SearchMultipleComponent } from './search-multiple.component';
+import { Instance } from '../../metamodel/models';
+import { ConeSearch, SearchMultipleQueryParams, SearchQueryParams } from '../store/models';
+
+describe('[Instance][SearchMultiple] SearchMultipleComponent', () => {
+    @Component({ selector: 'app-progress-bar-multiple', template: '' })
+    class ProgressBarMultipleStubComponent {
+        @Input() instance: Instance;
+        @Input() currentStep: string;
+        @Input() positionStepChecked: boolean;
+        @Input() datasetsStepChecked: boolean;
+        @Input() resultStepChecked: boolean;
+        @Input() coneSearch: ConeSearch;
+        @Input() selectedDatasets: string[];
+        @Input() queryParams: SearchMultipleQueryParams;
+    }
+
+    let component: SearchMultipleComponent;
+    let fixture: ComponentFixture<SearchMultipleComponent>;
+    let store: MockStore;
+
+    beforeEach(waitForAsync(() => {
+        TestBed.configureTestingModule({
+            imports: [RouterTestingModule],
+            declarations: [
+                SearchMultipleComponent,
+                ProgressBarMultipleStubComponent
+            ],
+            providers: [provideMockStore({ })]
+        }).compileComponents();
+        fixture = TestBed.createComponent(SearchMultipleComponent);
+        component = fixture.componentInstance;
+        store = TestBed.inject(MockStore);
+    }));
+
+    it('should create the component', () => {
+        expect(component).toBeDefined();
+    });
+});
diff --git a/client/src/app/instance/search-multiple/search-multiple.module.ts b/client/src/app/instance/search-multiple/search-multiple.module.ts
index fb571918658a6964da4044754d30fff003230838..2d155bd9c3da6134f4fa689fb0bf0f0cc50567be 100644
--- a/client/src/app/instance/search-multiple/search-multiple.module.ts
+++ b/client/src/app/instance/search-multiple/search-multiple.module.ts
@@ -14,6 +14,10 @@ import { ConeSearchModule } from '../cone-search/cone-search.module';
 import { SearchMultipleRoutingModule, routedComponents } from './search-multiple-routing.module';
 import { dummiesComponents } from './components';
 
+/**
+ * @class
+ * @classdesc Search multiple module.
+ */
 @NgModule({
     imports: [
         SharedModule,
diff --git a/client/src/test-data.ts b/client/src/test-data.ts
index 4928da851991c58df45b57a7d1d9bb96137ab093..683df725204adfb4dd6fa6fb5975530dbfef8c0d 100644
--- a/client/src/test-data.ts
+++ b/client/src/test-data.ts
@@ -1,4 +1,175 @@
-import { Attribute, Dataset, OutputCategory } from './app/metamodel/models';
+import { Attribute, Dataset, DatasetFamily, Instance, OutputCategory, Survey } from './app/metamodel/models';
+
+export const SURVEY_LIST: Survey[] = [
+    {
+        name: 'survey-one',
+        label: 'First survey',
+        description: 'This is the description of first survey',
+        link: 'http://survey-one.com',
+        manager: 'Marylin Monroe',
+        id_database: 1,
+        nb_datasets: 1
+    },
+    {
+        name: 'survey-two',
+        label: 'Second survey',
+        description: 'This is the description of second survey',
+        link: 'http://survey-two.com',
+        manager: 'FA',
+        id_database: 2,
+        nb_datasets: 2
+    }
+];
+
+export const INSTANCE: Instance = {
+    name: 'myInstance',
+    label: 'My Instance',
+    data_path: 'data/path',
+    config: {
+        design: {
+            design_color: 'green',
+            design_background_color: 'darker green',
+            design_logo: 'path/to/logo',
+            design_favicon: 'path/to/favicon'
+        },
+        home: {
+            home_component: 'HomeComponent',
+            home_config: {
+                home_component_text: 'Description',
+                home_component_logo: 'path/to/logo'
+            }
+        },
+        search: {
+            search_by_criteria_allowed: false,
+            search_by_criteria_label: 'Search',
+            search_multiple_allowed: false,
+            search_multiple_label: 'Search multiple',
+            search_multiple_all_datasets_selected: false
+        },
+        documentation: {
+            documentation_allowed: false,
+            documentation_label: 'Documentation'
+        }
+    },
+    nb_dataset_families: 1,
+    nb_datasets: 2
+};
+
+export const DATASET_FAMILY_LIST: DatasetFamily[] = [
+    { id: 2, label: 'My second dataset family', display: 2, opened: false },
+    { id: 1, label: 'My first dataset family', display: 1, opened: true }
+];
+
+export const DATASET_LIST: Dataset[] = [
+    {
+        name: 'myDataset',
+        table_ref: 'table',
+        label: 'my dataset',
+        description: 'This is my dataset',
+        display: 1,
+        data_path: 'path',
+        survey_name: 'mySurvey',
+        id_dataset_family: 1,
+        public: true,
+        full_data_path: '/data/path',
+        config: {
+            images: ['image'],
+            survey: {
+                survey_enabled: true,
+                survey_label: 'More about this survey'
+            },
+            cone_search: {
+                cone_search_enabled: true,
+                cone_search_opened: true,
+                cone_search_column_ra: 1,
+                cone_search_column_dec: 2,
+                cone_search_plot_enabled: true,
+                cone_search_sdss_enabled: true,
+                cone_search_sdss_display: 1,
+                cone_search_background: [{ id: 1, enabled: true, display: 1 }]
+            },
+            download: {
+                download_enabled: true,
+                download_opened: true,
+                download_csv: true,
+                download_ascii: true,
+                download_vo: true,
+                download_archive: true
+            },
+            summary: {
+                summary_enabled: true,
+                summary_opened: true
+            },
+            server_link: {
+                server_link_enabled: true,
+                server_link_opened: true
+            },
+            samp: {
+                samp_enabled: true,
+                samp_opened: true
+            },
+            datatable: {
+                datatable_enabled: true,
+                datatable_opened: true,
+                datatable_selectable_rows: true
+            }
+        }
+    },
+    {
+        name: 'anotherDataset',
+        table_ref: 'table',
+        label: 'amother dataset',
+        description: 'This is another dataset',
+        display: 2,
+        data_path: 'path',
+        survey_name: 'mySurvey',
+        id_dataset_family: 1,
+        public: true,
+        full_data_path: '/data/path',
+        config: {
+            images: ['image'],
+            survey: {
+                survey_enabled: true,
+                survey_label: 'More about this survey'
+            },
+            cone_search: {
+                cone_search_enabled: true,
+                cone_search_opened: true,
+                cone_search_column_ra: 1,
+                cone_search_column_dec: 2,
+                cone_search_plot_enabled: true,
+                cone_search_sdss_enabled: true,
+                cone_search_sdss_display: 1,
+                cone_search_background: [{ id: 1, enabled: true, display: 1 }]
+            },
+            download: {
+                download_enabled: true,
+                download_opened: true,
+                download_csv: true,
+                download_ascii: true,
+                download_vo: true,
+                download_archive: true
+            },
+            summary: {
+                summary_enabled: true,
+                summary_opened: true
+            },
+            server_link: {
+                server_link_enabled: true,
+                server_link_opened: true
+            },
+            samp: {
+                samp_enabled: true,
+                samp_opened: true
+            },
+            datatable: {
+                datatable_enabled: true,
+                datatable_opened: true,
+                datatable_selectable_rows: true
+            }
+        }
+    },
+];
 
 export const DATASET: Dataset = {
     name: 'myDataset',