2017-12-04 8 views
0

의 기능을 조롱합니다. 이 패키지의 각 파일은 서비스에 해당합니다. 예를 들어 제품 파일은 제품 서비스/db, 주문 서비스 주문 등과 관련된 기능을 포함합니다. 각 함수는 매개 변수로 기본 db에 대한 db 리소스를 가져오고 SQL, 예. productid, 이름, 주문 ID.어떻게 기본적으로 게터 기능의 많은 구성 간단한 패키지를 작성했습니다 golang

// product.go 

package lib 

type Product struct { 
    ID int 
    Name string 
    Price float 
} 

func GetProductById(DB *sql.DB, ID int) (p Product, err error) { 
    q := "SELECT * FROM product WHERE id = " + ID 
    ... 
} 

func GetProductByName(DB *sql.DB, name string) (p Product, err error) { 
    ... 
} 

// order.go 

package lib 

type Order struct { 
    ID int 
    Date string 
    Items []items 
} 

func GetOrderById(DB *sql.DB, ID int) (o Order, err error) { 
    ... 
} 

문제는 내 기본 패키지에서 이러한 기능을 조롱 할 수 아니에요입니다 : 함수의 각 구조체 (. 예를 들어, 주문, 제품) 또는 오류를 반환합니다. 내가 정말로하고 싶은 것은 패키지를 다시 작성하는 것입니다. 그래서 어떻게 든 함수로 전달할 수 있습니다. 하지만 어떻게해야할지 모르겠습니다. 특히 함수가 다른 입력 매개 변수를 사용하고 다른 struct를 반환하는 경우가 아닙니다. 이것을 할 수있는 방법이 있습니까? 당신이 구체적인 유형에 대한 메소드 선언과 같은 함수 선언을 조롱 할 수없는 이동에

답변

2

, 당신은 사람들을 조롱 수 없습니다. 예를 들어

:

func F() 

func (T) M() 

FM는 이동에 mockable 수 없습니다. 당신은 그들이 변수, 구조체의 필드, 또는 다른 함수에 전달 된 매개 변수인지, 함수 값을 조롱 할 수 그러나


. 예를 들어

: 세 가지 경우 모두에서

var Fn = func() { ... } 

type S struct { 
    Fn func() 
} 

func F(Fn func()) 

Fn는 mockable입니다.


당신이 이동에 조롱 할 수있는 다른 것은, 시간의 가장 선호하는 옵션은 interface입니다. 예를 들어

: 이제 ProductRepository에 따라 코드의 조각 유형 ProductStore는 "일반 모드"에있어의 가치와 당신이있어 유형 ProductRepositoryMock의 값을 전달할 수 있습니다

type ProductRepository interface { 
    GetProductById(DB *sql.DB, ID int) (p Product, err error) 
} 

// the real implementater of the interface 
type ProductStore struct{} 

func (ProductStore) GetProductById(DB *sql.DB, ID int) (p Product, err error) { 
    q := "SELECT * FROM product WHERE id = " + ID 
    // ... 
} 

// the mock implementer 
type ProductRepositoryMock struct {} 

func (ProductRepositoryMock) GetProductById(DB *sql.DB, ID int) (p Product, err error) { 
    // ... 
} 

테스트.


당신이 대부분 unchaged이 유형이 당신의 기능에 전달하기로 그 인터페이스 유형을 사용 *sql.DB의 방법을 모방 인터페이스를 정의하는 것입니다 기능을 유지할 수 있습니다 interface의를 사용하여 또 다른 옵션을, 해당 인터페이스의 모의 버전을 구현하고 테스트하는 동안 그것을 사용하십시오. 예를 들어

:

type DBIface interface { 
    Query(query string, args ...interface{}) (*sql.Rows, error) 
    // ... 
    // It's enough to implement only those methods that 
    // the functions that depend on DBIface actually use. 
    // If none of your functions ever calls SetConnMaxLifetime 
    // you don't need to declare that method on the DBIface type. 
} 

type DBMock struct {} 

func (DBMock) Query(query string, args ...interface{}) (*sql.Rows, error) { 
    // ... 
} 

func GetProductByName(DB DBIface, name string) (p Product, err error) { 
    ... 
} 

DB 파라미터 GetProductByName에 지금 mockable이다.