2 回答
TA贡献1812条经验 获得超5个赞
你也可以嵌入
type MySelection struct {
goquery.Selection
some payload //if needed
}
并且您将免费获得 MySelection 的 goquery.Selection 方法,并且可以添加或覆盖一些方法。
TA贡献1872条经验 获得超3个赞
嗯,有几种方法可以“处理这个”。但不要说出它的名字Get()
:它不是惯用的。
从最佳实践的角度来看,我建议:
将他们的代码与您的代码分离。
实现反腐败层(包装他们的包的包装器)
造成这种情况的原因很多。但是对于 Go 来说,最好保持简单——这归结为一个问题:你想对你的代码进行单元测试吗?
如果答案是肯定的,那么我永远不会直接使用 3rd 方包。我会用我自己的界面包装他们的包。然后,在我的所有代码中使用(注入)该接口,以便我可以在单元测试中模拟它。
同样有几种模式和观点;但是,我将展示这个允许单元测试的包装器。
goquery_wrapper.go
package mypackage
import (
"path/to/goquery.Selection"
)
var _mySelector *mySelector // Go stdlib uses underscores for private types
type mySelector interface {
Html() string
...
}
type MySelector struct {
}
func (ms *MySelector) Html() {
// your custom version
}
// initialize the global var with your wrapper
func init() {
_mySelector = &MySelector{ ... }
}
foo.go
package mypackage
func Foo() {
// uses the global var initialized with init()
data := _mySelector.Html()
// IoC using D.I. through constructors
obj := NewSomething(_mySelector)
// IoC using D.I. through methods
result := bar.Process(_mySelector, "input data")
}
bar_test.go
package mypackage
import (
"testing"
)
type mockSelector struct {
HtmlWasCalled bool
HtmlReturnsThis string
}
func (ms mockSelector) Html() string {
ms.HtmlWasCalled = true
return ms.HtmlReturnsThis
}
func TestBar(t *testing.T) {
// arrange
// override your global var
oldMS := _mySelector
_mySelector := &mockSelector{
HtmlReturnsThis: "<b>success</b>",
}
// act
// since foo.Bar is using the global var, it now uses
// our mock we set above.
result := foo.Bar("sample input")
// assert
if result != expected {
t.Fail()
}
// put it back the way it was
_mySelector = oldMS
}
func TestFoo(t *testing.T) {
// arrange
mock := &mockSelector{
HtmlReturnsThis: "<b>success</b>",
}
// act
// or, just inject your mock if using IoC
result := bar.Process(mock, "sample input")
// assert
...
}
这使我不必在单元测试期间处理 3rd 方包的细微差别。效果很好,除非包的 API 很大。然后,我什至质疑为什么我开始使用这个包,如果它那么复杂。
- 2 回答
- 0 关注
- 153 浏览
添加回答
举报