Sfoglia il codice sorgente

Add milvus module tests

tumao 3 anni fa
parent
commit
7bc0b5678d

+ 17 - 15
.github/workflows/dev.yml

@@ -25,7 +25,9 @@ jobs:
       - name: Upload coverage to Codecov
         uses: codecov/codecov-action@v2
         with:
+          # public repo needn't pass token
           # token: ${{ secrets.CODECOV_TOKEN }}
+          # only upload express test coverage
           flags: express
 
       - name: Login to DockerHub
@@ -78,19 +80,19 @@ jobs:
   #         sleep 60
 
   # check:
-  # runs-on: ubuntu-latest
-  # needs: [build, k8s]
-  # steps:
-  #   - uses: actions/checkout@v2
-  #   - name: Setup Node.js
-  #     uses: actions/setup-node@v1
-  #     with:
-  #       node-version: 12
+    # runs-on: ubuntu-latest
+    # needs: [build, k8s]
+    # steps:
+    #   - uses: actions/checkout@v2
+    #   - name: Setup Node.js
+    #     uses: actions/setup-node@v1
+    #     with:
+    #       node-version: 12
 
-  #   - name: Check insight status
-  #     env:
-  #       INSIGHT_URL: ${{ secrets.INSIGHT_URL }}
-  #     run: |
-  #       yarn add axios
-  #       yarn add @actions/core
-  #       node checkInsight.js
+    #   - name: Check insight status
+    #     env:
+    #       INSIGHT_URL: ${{ secrets.INSIGHT_URL }}
+    #     run: |
+    #       yarn add axios
+    #       yarn add @actions/core
+    #       node checkInsight.js

+ 3 - 2
express/package.json

@@ -16,13 +16,14 @@
   },
   "jest": {
     "testEnvironment": "node",
+    "testTimeout": 10000,
     "coveragePathIgnorePatterns": [
       "/node_modules/"
     ],
     "rootDir": "src",
     "testRegex": ".*\\.test\\.ts$",
     "collectCoverageFrom": [
-      "**/*.{js,ts}"
+      "**/*.service.{js,ts}"
     ],
     "transform": {
       "^.+\\.(t|j)s$": "ts-jest"
@@ -54,7 +55,7 @@
     "start:prod": "node dist/app.js",
     "test": "cross-env NODE_ENV=test jest --passWithNoTests",
     "test:watch": "jest --watch",
-    "test:cov": "cross-env NODE_ENV=test jest --passWithNoTests --coverage",
+    "test:cov": "cross-env NODE_ENV=test jest --passWithNoTests --coverage --detectOpenHandles",
     "test:report": "cross-env NODE_ENV=test jest --watchAll=false --coverage --coverageReporters='text-summary'",
     "clean": "rimraf dist"
   }

+ 9 - 0
express/src/__mocks__/milvus/milvus.service.ts

@@ -0,0 +1,9 @@
+const mockMivusService = jest.fn().mockImplementation(() => {
+  return {
+    connectMilvus: (address: string) => new Promise(() => !!address),
+    checkConnect: (address: string) => new Promise(() => address),
+    flush: (collectionName: string) => new Promise(() => collectionName),
+  };
+});
+
+export default mockMivusService;

+ 33 - 0
express/src/__mocks__/milvus/milvusClient.ts

@@ -0,0 +1,33 @@
+import { FlushReq } from '@zilliz/milvus2-sdk-node/dist/milvus/types';
+
+const mockMilvusClient = jest.fn().mockImplementation((address: string) => {
+  return {
+    collectionManager: {
+      hasCollection: (param: { collection_name: string }) => {
+        const { collection_name } = param;
+        if (address === '') {
+          throw new Error('no address');
+        }
+        return collection_name;
+      },
+    },
+    partitionManager: {},
+    indexManager: {},
+    dataManager: {
+      flush: (data: FlushReq) => ({
+        data,
+      }),
+      getMetric: (data: { request: { metric_type: string } }) => {
+        const {
+          request: { metric_type: type },
+        } = data;
+
+        return {
+          type,
+        };
+      },
+    },
+  };
+});
+
+export default mockMilvusClient;

+ 46 - 12
express/src/__tests__/milvus/index.test.ts

@@ -1,19 +1,53 @@
-import request from 'supertest';
 import express from 'express';
+import http from 'http';
+import supertest from 'supertest';
 import { router as connectRouter } from '../../milvus/index';
+import { TransformResInterceptor } from '../../interceptors';
+import MilvusService from '../../__mocks__/milvus/milvus.service';
+import { mockAddress } from '../utils/Consts';
 
-const app = express();
-const router = express.Router();
-router.use('/milvus', connectRouter);
-app.use('/api/v1', router);
-
-// mock service that
+// mock Milvus client service
+jest.mock('../../__mocks__/milvus/milvus.service');
 
 describe('Test Milvus Module', () => {
-  test('check whether connected to Milvus', async () => {
-    const res = await request(app).get('/check');
-    expect(res.header['content-type']).toBe('text/html; charset=utf-8');
-    expect(res.statusCode).toBe(404);
-    // expect(res.text).toEqual(true);
+  let app: any;
+  let server: any;
+  let request: any;
+
+  // setup app and server
+  beforeAll((done) => {
+    app = express();
+    const router = express.Router();
+    router.use('/milvus', connectRouter);
+    app.use(TransformResInterceptor);
+    app.use('/api/v1', router);
+    server = http.createServer(app);
+    server.listen(done);
+    request = supertest(server);
+  });
+
+  beforeEach(() => {
+    // Clear all instances and calls to constructor and all methods:
+    MilvusService.mockClear();
+  });
+
+  // close server
+  afterAll((done) => {
+    server.close(done);
+  });
+
+  test('check whether connected to Milvus with address', () => {
+    // with address param
+    request.get('/check').query({ address: mockAddress }).expect(200);
+    // without address param
+    request.get('/check').expect(404);
+  });
+
+  test('check request to connect to Milvus', () => {
+    request
+      .post('/connect')
+      .send({ address: mockAddress })
+      .set('Accept', 'application/json')
+      .expect(200);
   });
 });

+ 82 - 0
express/src/__tests__/milvus/milvus.service.test.ts

@@ -0,0 +1,82 @@
+import mockMilvusClient from '../../__mocks__/milvus/milvusClient';
+import { MilvusService } from '../../milvus/milvus.service';
+import { mockAddress } from '../utils/Consts';
+
+// mock Milvus client
+jest.mock('@zilliz/milvus2-sdk-node', () => {
+  return {
+    MilvusClient: mockMilvusClient,
+  };
+});
+
+describe('Test Milvus service', () => {
+  let service: any;
+
+  // init service
+  beforeEach(() => {
+    service = new MilvusService();
+  });
+
+  afterEach(() => {
+    service = null;
+  });
+
+  test('test connectMilvus method', async () => {
+    expect(service.milvusClientGetter).toBeUndefined();
+    expect(service.milvusAddressGetter).toBe('');
+
+    const res = await service.connectMilvus(mockAddress);
+    expect(res.address).toBe(mockAddress);
+    expect(service.milvusAddressGetter).toBe(mockAddress);
+    expect(service.milvusClientGetter).toBeDefined();
+  });
+
+  test('test connectMilvus method error', async () => {
+    try {
+      await service.connectMilvus('');
+    } catch (err) {
+      expect(err.message).toBe(
+        'Connect milvus failed, check your milvus address.'
+      );
+    }
+  });
+
+  test('test checkMilvus when not connect to Milvus', () => {
+    try {
+      service.checkMilvus();
+    } catch (err) {
+      expect(err.message).toBe('Please connect milvus first');
+    }
+  });
+
+  test('test checkConnect method', async () => {
+    // mock connect first
+    await service.connectMilvus(mockAddress);
+    // different address
+    const errorRes = await service.checkConnect('123');
+    expect(errorRes.connected).toBeFalsy();
+    const res = await service.checkConnect(mockAddress);
+    expect(res.connected).toBeTruthy();
+  });
+
+  test('test managers after connected', async () => {
+    await service.connectMilvus(mockAddress);
+    expect(service.collectionManager).toBeDefined();
+    expect(service.partitionManager).toBeDefined();
+    expect(service.indexManager).toBeDefined();
+    expect(service.dataManager).toBeDefined();
+  });
+
+  test('test flush method', async () => {
+    await service.connectMilvus(mockAddress);
+    const res = await service.flush({ collection_names: ['c1', 'c2'] });
+    const data = res.data.collection_names;
+    expect(data.length).toBe(2);
+  });
+
+  test('test getMetrics method', async () => {
+    await service.connectMilvus(mockAddress);
+    const res = await service.getMetrics();
+    expect(res.type).toBe('system_info');
+  });
+});

+ 2 - 0
express/src/__tests__/utils/consts.ts

@@ -0,0 +1,2 @@
+export const mockAddress = '127.0.0.1'
+export const mockPort = 3001

+ 1 - 1
express/src/app.ts

@@ -21,7 +21,7 @@ const PLUGIN_DEV = process.env?.PLUGIN_DEV;
 const SRC_PLUGIN_DIR = "src/plugins";
 const DEV_PLUGIN_DIR = "../../src/*/server";
 
-const app = express();
+export const app = express();
 const PORT = 3000;
 // initialize a simple http server
 const server = http.createServer(app);

+ 8 - 8
express/src/milvus/milvus.service.ts

@@ -1,15 +1,15 @@
-import { MilvusClient } from "@zilliz/milvus2-sdk-node";
+import { MilvusClient } from '@zilliz/milvus2-sdk-node';
 import {
   FlushReq,
   GetMetricsResponse,
-} from "@zilliz/milvus2-sdk-node/dist/milvus/types";
+} from '@zilliz/milvus2-sdk-node/dist/milvus/types';
 
 export class MilvusService {
   private milvusAddress: string;
   private milvusClient: MilvusClient;
 
   constructor() {
-    this.milvusAddress = "";
+    this.milvusAddress = '';
   }
 
   get milvusAddressGetter() {
@@ -42,22 +42,22 @@ export class MilvusService {
 
   private checkMilvus() {
     if (!this.milvusClient) {
-      throw new Error("Please connect milvus first");
+      throw new Error('Please connect milvus first');
     }
   }
 
   async connectMilvus(address: string) {
     // grpc only need address without http
-    const milvusAddress = address.replace(/(http|https):\/\//, "");
+    const milvusAddress = address.replace(/(http|https):\/\//, '');
     try {
       this.milvusClient = new MilvusClient(milvusAddress);
       await this.milvusClient.collectionManager.hasCollection({
-        collection_name: "not_exist",
+        collection_name: 'not_exist',
       });
       this.milvusAddress = address;
       return { address: this.milvusAddress };
     } catch (error) {
-      throw new Error("Connect milvus failed, check your milvus address.");
+      throw new Error('Connect milvus failed, check your milvus address.');
     }
   }
 
@@ -78,7 +78,7 @@ export class MilvusService {
 
   async getMetrics(): Promise<GetMetricsResponse> {
     const res = await this.milvusClient.dataManager.getMetric({
-      request: { metric_type: "system_info" },
+      request: { metric_type: 'system_info' },
     });
     return res;
   }