Go의 모의 데이터베이스

11331 단어 godatabasetesting
우리 모두는 실제로 모든 데이터베이스에 적중하는 단위 테스트를 작성하는 것이 단위 테스트를 작성하는 것이 아니라는 것을 알고 있지만 많은 사람들이 프로덕션 등급 소프트웨어를 실행하는 회사에서도 여전히 수행합니다.

플랫폼과 각 컴퓨터의 구성에 따라 달라지는 파일 시스템과 상호 작용하는 테스트를 작성하는 것처럼 테스트 데이터베이스에 대해 "행복한"상태를 설정하고 이에 대해 테스트를 실행하고 상태를 해제해야 하는 테스트는 통제할 수 없는 것을 통제하려 할 뿐이다. 테스트에서 더 많은 버그가 발생하기를 기다리고 있습니다.

그래서 Go에서 데이터베이스를 조롱하는 방법을 간략히 소개하고자 합니다. 보다 구체적으로 *sql.DB .

다음은 데이터베이스를 사용하여 작업을 수행하는 샘플 함수입니다.

func SaveUserToDB(db *sql.DB, user *User) error {
        _, err := db.Exec(`                                                                                                                          
            INSERT INTO usr (name, email_address, created)                                                                                                                                                                                                                                                                                                                                                                                       
            VALUES ($1, $2, $3);`, 
            user.Name, user.EmailAddress, time.Now(),
        ) 
        if err != nil {
                return err
        }
        return nil
}


실제로, 이 간결한 함수에 대한 테스트를 작성하는 것은 귀하에게 가장 좋은 것이 아닙니다. DB 인스턴스에서 Exec()를 호출하는 것 외에는 아무 것도 하지 않습니다. 잘 테스트된 패키지를 신뢰한다면 테스트할 필요가 없습니다. 그러나 예를 들어 완벽합니다.

항상 종속성 주입을 선택하고 함수가 *sql.DB 인스턴스를 인수로 받아들이도록 합니다.

이 경우 Exec 메서드를 테스트하려고 합니다. 모의 객체를 *sql.DB 로 한정하는 인터페이스를 만들어야 합니다. 이제 database/sql 문서를 들여다보고 DB.Exec 의 서명을 확인할 시간입니다.

func (db *sql.DB) Exec(query string, args ...interface{}) (sql.Result, error)


이제 이 서명으로 인터페이스를 만들어 보세요.

type SQLDB interface {
        Exec(query string, args ...interface{}) (sql.Result, error)
}

*sql.DB 이 메서드를 구현하므로 SQLDB 로 규정됩니다.
이제 우리는 우리 자신의 모의 DB의 구현을 편안하게 생성할 수 있습니다:

type MockDB struct {}

// Implement the SQLDB interface
func (mdb *MockDB) Exec(query string, args ...interface{}) (sql.Result, error) {
        return nil, nil
}

nil에 대해 sql.Result를 반환한다는 점에 유의하십시오. 이 값은 신경 쓰지 않기 때문입니다. 그렇게 하면 유형에 대해 다른 인터페이스를 구현해야 합니다.

이제 모의 객체가 호출될 때의 상태를 기록하기를 원하므로 callParams 구조체에 MockDB라는 유용한 필드를 추가하여 호출될 때 매개변수를 기록합니다.

type MockDB struct {
        callParams []interface{}
}

func (mdb *MockDB) Exec(query string, args ...interface{}) sql.Result, error) {
        mdb.callParams = []interface{}{query}
        mdb.callParams = append(mdb.callParams, args...)

        return nil, nil
}

// Add a helper method to inspect the `callParams` field
func (mdb *MockDB) CalledWith() []interface{} {
        return mdb.callParams
}



마지막 변경(그러나 매우 중요한 변경)은 테스트SaveUserToDB에서 SQLDB 인스턴스 대신 *sql.DB 인터페이스를 허용하도록 함수를 만드는 것입니다. 이런 식으로 우리는 *MockDB를 넣을 수 있습니다.

func SaveUserToDB(db SQLDB, user *User) error {
        // No changes
}


다음은 이 함수에 대한 테스트를 작성하는 방법의 예입니다.


import (
        "testing"
        "github.com/stretchr/testify/assert"
)

func TestSaveUserToDB(t *testing.T) {

        // Create a new instance of *MockDB
        mockDB := new(MockDB)

        // Call the function with mock DB
        SaveUserToDB(mockDB, &User{"Joe", "[email protected]"})


        params := mockDB.CalledWith()

        // Normally we shouldn't test equality of query strings
        // since you might miss some formatting quirks like newline
        // and tab characters.
        expectedQuery := `                                                                                                                          
            INSERT INTO usr (name, email_address, created)                                                                                                                                                                                                                                                                                                                                                                                       
            VALUES ($1, $2, $3);`

        // Assert that the first parameter in the call was SQL query
        assert.Equal(t, params[0], expectedQuery)
}


이제 이것이 Go 코드에서 더 많은 "단단한"DB 테스트를 작성하도록 권장할 수 있기를 바랍니다. Go로 무엇을 하는지 관심이 있으시면 앱 및 서비스에 대한 초대 전용 캠페인을 구축하기 위한 개발자 친화적인 API 및 SDK인 Referkit을 확인하십시오.

좋은 웹페이지 즐겨찾기