sourcecode

Node.js에서 MySQL(ORM 없음)을 어떻게 조롱합니까?

copyscript 2022. 9. 5. 23:13
반응형

Node.js에서 MySQL(ORM 없음)을 어떻게 조롱합니까?

하고 Node.js펠릭스의 의뢰인과 함께요ORM을 사용하지 않습니다.

때문에 (DAL 이외의)node-mysql 할지 잘 CRUD가 있습니다.

어떻게 이 일을 해낼지 생각나는 거 없어?

사용하면을 붙일 수 .sinon은 모듈 전체에 mock 또는 을 붙일 수 있습니다.를 들어, '아까다', '아까다'가 있다고 해 보겠습니다.mysql 에는 "Module" 의 .query:

var mock;

mock = sinon.mock(require('mysql'))
mock.expects('query').with(queryString, queryParams).yields(null, rows);

queryString,queryParams예상되는 입력입니다. rows예상되는 출력입니다.

로 하는 mysql을 합니다.query방법은 시논에 의해 차단되고 검증됩니다.

테스트 예상 섹션에서 다음을 수행해야 합니다.

mock.verify()

해체 시 mysql을 정상 기능으로 복원해야 합니다.

mock.restore()

데이터베이스를 mysql을 사용하는 자체 클래스로 추상화하는 것이 좋습니다.그런 다음 해당 클래스의 인스턴스를 require()를 사용하여 로드하는 대신 모델 생성자에게 전달할 수 있습니다.

이 설정을 통해 장치 테스트 파일 내의 모델에 모의 DB 인스턴스를 전달할 수 있습니다.

다음은 작은 예입니다.

// db.js
var Db = function() {
   this.driver = require('mysql');
};
Db.prototype.query = function(sql, callback) {
   this.driver... callback (err, results);
}
module.exports = Db;

// someModel.js
var SomeModel = function (params) {
   this.db = params.db
}
SomeModel.prototype.getSomeTable (params) {
   var sql = ....
   this.db.query (sql, function ( err, res ) {...}
}
module.exports = SomeModel;

// in app.js
var db = new (require('./db.js'))();
var someModel = new SomeModel ({db:db});
var otherModel = new OtherModel ({db:db})

// in app.test.js
var db = {
   query: function (sql, callback) { ... callback ({...}) }
}
var someModel = new SomeModel ({db:db});

node.js에 대해서는 잘 모릅니다만, 종래의 프로그래밍의 의미에서는, 이러한 테스트를 실시하려면 , 데이터 액세스 방법으로부터 추상화할 필요가 있습니다.다음과 같은 DAL 클래스를 만들 수 없습니까?

var DataContainer = function () {
}

DataContainer.prototype.getAllBooks = function() {
    // call mysql api select methods and return results...
}

이제 테스트의 맥락에서 초기화 중에 다음과 같이 getAllBooks 클래스에 패치를 적용합니다.

DataContainer.prototype.getAllBooks = function() {
    // Here is where you'd return your mock data in whatever format is expected.
    return [];
}

테스트 코드가 호출되면 getAllBooks는 실제로 mysql을 호출하지 않고 모의 데이터를 반환하는 버전으로 대체됩니다.node.js에 대해서는 잘 모르기 때문에 대략적인 개요입니다.

저는 @kgilpin의 답변으로 시작해서 AWS Lambda에서 Mysql을 테스트하기 위해 다음과 같은 결과를 얻었습니다.

const sinon = require('sinon');
const LambdaTester = require('lambda-tester');
const myLambdaHandler = require( '../../lambdas/myLambda' ).handler;
const mockMysql = sinon.mock(require('mysql'));
const chai = require('chai');
const expect = chai.expect;

describe('Database Write Requests', function() {

 beforeEach(() => {
   mockMysql.expects('createConnection').returns({
     connect: () => {
       console.log('Succesfully connected');
     },
     query: (query, vars, callback) => {
       callback(null, succesfulDbInsert);
     },
     end: () => {
       console.log('Connection ended');
     }
   });

 });
 after(() => {
   mockMysql.restore();
 });

 describe( 'A call to write to the Database with correct schema', function() {

   it( 'results in a write success', function() {

     return LambdaTester(myLambdaHandler)
       .event(anObject)
       .expectResult((result) => {
         expect(result).to.equal(succesfulDbInsert);
       });
   });
 });


 describe( 'database errors', function() {

   before(() => {
     mockMysql.expects('createConnection').returns({
       connect: () => {
         console.log('Succesfully connected');
       },
       query: (query, vars, callback) => {
         callback('Database error!', null);
       },
       end: () => {
         console.log('Connection ended');
       }
     });
   });

   after(() => {
     mockMysql.restore();
   });

   it( 'results in a callback error response', function() {


     return LambdaTester(myLambdaHandler)
       .event(anObject)
       .expectError((err) => {
         expect(err.message).to.equal('Something went wrong');
       });
   });
 });
});

실제 데이터베이스 접속을 원하지 않았기 때문에 mysql 응답을 모두 수동으로 조롱했습니다.
는 by田에 다른 했습니다..returns 할 수 createConnection.

hora를 사용하여 외부 종속성을 조롱할 수 있습니다.

또한 필릭스의 노드 샌드박스 모듈도 비슷한 기능을 할 수 있다고 생각합니다.

따라서 kgilpin의 동일한 컨텍스트를 사용하면 hora에서는 다음과 같이 됩니다.

var mock = horaa('mysql');
mock.hijack('query', function(queryString, queryParam) {
    // do your fake db query (e.g., return fake expected data)
});

//SUT calls and asserts

mock.restore('query');

mysql 드라이버를 사용하려면 먼저 연결을 만들고 반환된 연결 컨트롤러의 apis를 사용해야 하므로 2단계 접근법이 필요합니다.

그것을 하는 데는 두 가지 방법이 있습니다.

createConnection을 stubbing하여 stubbed 연결을 반환한다.

셋업 중:

const sinon = require('sinon');
const mysql = require('mysql');
const {createConnection} = mysql;
let mockConnection;
sinon.stub(mysql, 'createConnection').callsFake((...args) => {
    mockConnection = sinon.stub(createConnection.apply(mysql, args))
      .expects('query').withArgs(.... )//program it how you like :)
    return mockConnection;
})

const mockConnectionFactory = 
  sinon.stub(mysql)
  .expects('createConnection')

해체 중:

mysql.createConnection.restore();

여기서 주의할 점은query방법은 사례에서 조롱되고, 기초적인 메카니즘에 아무런 함의가 없기 때문에, 오직createConnection를 복원해야 합니다.

stubbing, 접속 프로토타입에서의 .timeout 메서드

이 기술은 조금 더 까다롭습니다.mysql드라이버가 공식적으로 Import 연결을 노출하지 않습니다.(접속을 구현하는 모듈만 Import할 수 있지만 리팩터링이 해당 모듈로 이동하지 않는다는 보장은 없습니다).프로토타입에 대한 참조를 얻기 위해 보통 연결을 만들고 생성자-프로토타입 체인을 따라 이동합니다.

보통 한 줄로 진행하는데, 단계별로 나누어 설명하겠습니다.

셋업 중:

const realConnection = mysql.createConnection({})
const mockTarget = realConnection.constructor.prototype;
//Then - brutally
consdt mock = sinon.mock(mockTarget).expect('query'....
//OR - as I prefer the surgical manner
sinon.stub(mockTarget, 'query').expect('query'....

해체 중

//brutal
mock.restore()
// - OR - surgical:
mockTarget.query.restore()

주의해 주세요.createConnection방법은 이쪽입니다.모든 접속 파라미터 검증은 계속 진행됩니다(이러한 검증이 이루어지길 바랍니다).저는 최대한의 정규 부품으로 작업하고 싶습니다.따라서 빠른 테스트를 받기 위해 필요한 절대적인 최소 부품을 조롱합니다.)단, -query프로토타입에서 조롱당했으므로 복원해야 합니다.

그리고 만약 당신이 수술을 한다면verifymockTarget이 아닌 mockTarget에 있습니다.

여기 좋은 리소스가 있습니다.http://devdocs.io/sinon ~ 6 ~ 6 ~720s /

언급URL : https://stackoverflow.com/questions/8389149/how-do-you-mock-mysql-without-an-orm-in-node-js

반응형