[英]issue with dependency injection with interface
我有提供與tcp連接一起工作的軟件包,基本上是這樣的:
package connpool
import (
"io/ioutil"
"net/http"
)
type ConnPool struct{}
func (pool *ConnPool) GetConn() Conn {
return Conn{}
}
func (pool *ConnPool) ReleaseConnection(conn Conn) {
}
type Conn struct{}
func (c Conn) FetchUrl(url string) ([]byte, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return []byte{}, err
}
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
return body, nil
}
然后我嘗試在另一個程序包中使用它,但按接口將其包裝起來,因為我想用假connpool在測試環境中替換此程序包
package main
import (
"connpool"
"fmt"
)
func onlyDependencyOnConnPool() *connpool.ConnPool {
return &connpool.ConnPool{}
}
type ConnPoolInterface interface {
GetConn() ConnInterface
ReleaseConnection(ConnInterface)
}
type ConnInterface interface {
FetchUrl(string) ([]byte, error)
}
type Fetcher struct{}
func (f Fetcher) Fetch(cPool ConnPoolInterface) error {
conn := cPool.GetConn()
defer cPool.ReleaseConnection(conn)
body, err := conn.FetchUrl("http://localhost:9200")
fmt.Println("body: ", string(body))
return err
}
func main() {
pool := onlyDependencyOnConnPool()
f := Fetcher{}
f.Fetch(pool)
}
但是它將在編譯時返回錯誤:
./main.go:34: cannot use pool (type *connpool.ConnPool) as type ConnPoolInterface in argument to f.Fetch:
*connpool.ConnPool does not implement ConnPoolInterface (wrong type for GetConn method)
have GetConn() connpool.Conn
want GetConn() ConnInterface
有沒有辦法在每個文件中沒有connpool導入的情況下通過接口包裝此依賴項?
我只需要它來模擬測試環境中的http請求,就像這樣(如果我要在connpool包中實現接口,則我必須在其中實現每個模擬結構,看起來就像是一團糟):
package main
import(
"testing"
)
type FakeConnPool struct{}
func (pool *FakeConnPool) GetConn() FakeConn {
return FakeConn{}
}
func (pool *FakeConnPool) ReleaseConnection(conn FakeConn) {
}
type FakeConn struct{}
func (c FakeConn) FetchUrl(url string) ([]byte, error) {
println(url)
body := []byte(`{"status" : 200}`)
return body, nil
}
func changeDependency() ConnPoolInterface {
return &FakeConnPool{}
}
func TestBaz(t *testing.T) {
pool := changeDependency()
f := Fetcher{}
err := f.Fetch(pool)
if err != nil {
t.Errorf("error")
}
}
第一步,將您對GetConn
的聲明稍微更改為以下內容:
func (pool *ConnPool) GetConn() ConnInterface { // Conn -> ConnInterface
return Conn{}
}
那應該滿足ConnPoolInterface
的接口。 您可能必須稍稍重新排列代碼,以免之后出現循環依賴。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.