我已经整理了一段在我的路线上执行GET的代码。我想用模拟测试一下。我是Go和测试菜鸟,所以任何提示都非常感谢。
My Generate Routes.go生成当前URL的路由。 片段:
func (h *StateRoute) GenerateRoutes (router *martini.Router) *martini.Router {
r := *router
/**
* Get all states
*
*/
r.Get("/state", func( enc app.Encoder,
db abstract.MongoDB,
reqContext abstract.RequestContext,
res http.ResponseWriter,
req *http.Request) (int, string) {
states := []models.State{}
searchQuery := bson.M{}
var q *mgo.Query = db.GetDB().C("states").Find(searchQuery)
query, currentPage, limit, total := abstract.Paginate(req, q)
query.All(&states)
str, err := enc.EncodeWithPagination(currentPage, limit, total, states)
return http.StatusOK, app.WrapResponse(str, err)
})
}
这是在我的server.go中调用的。
var configuration = app.LoadConfiguration(os.Getenv("MYENV"))
// Our Martini API Instance
var apiInstance *martini.Martini
func init() {
apiInstance = martini.New()
// Setup middleware
apiInstance.Use(martini.Recovery())
apiInstance.Use(martini.Logger())
// Add the request context middleware to support contexual data availability
reqContext := &app.LRSContext{ }
reqContext.SetConfiguration(configuration)
producer := app.ConfigProducer(reqContext)
reqContext.SetProducer(producer)
apiInstance.MapTo(reqContext, (*abstract.RequestContext)(nil))
// Hook in the OAuth2 Authorization object, to be processed before all requests
apiInstance.Use(app.VerifyAuthorization)
// Connect to the DB and Inject the DB connection into Martini
apiInstance.Use(app.MongoDBConnect(reqContext))
// Add the ResponseEncoder to allow JSON encoding of our responses
apiInstance.Use(app.ResponseEncoder)
// Add Route handlers
r := martini.NewRouter()
stateRouter := routes.StateRoute{}
stateRouter.GenerateRoutes(&r)
// Add the built router as the martini action
apiInstance.Action(r.Handle)
}
我的怀疑:
这里的模拟是如何工作的,考虑到我正在尝试注入依赖项?
我应该从哪里开始测试,即我应该模拟r.Get in Generate Routes?现在,我已经做到了这一点但是因为我使用Martini来处理所有的路由和请求,如果我做的是对的话,我引用丢失了吗?
< / LI> 醇>state_test.go:
type mockedStateRoute struct {
// How can I mock the stateRoute struct?
mock.Mock
}
type mockedEncoder struct {
mock.Mock
}
type mockedMongoDB struct {
mock.Mock
}
type mockedReqContext struct{
mock.Mock
}
type mockedRespWriter struct{
mock.Mock
}
type mockedReq struct{
mock.Mock
}
func (m *mockedStateRoute) testGetStatesRoute(m1 mockedEncoder,
m2 mockedMongoDB, m3 mockedReqContext,
m4 mockedReqContext, m5 mockedRespWriter,
m6 mockedReq) (string) {
args := m.Called(m1,m2,m3,m4,m5,m6)
fmt.Print("You just called /states/GET")
// 1 is just a test value I want to return
return 1, args.Error(1)
}
func TestSomething (t *testing.T) {
testObj := new(mockedStateRoute)
testObj.On("testGetStatesRoute", 123).Return(true,nil)
// My target function that does something with mockedStateRoute
// How can I call the GET function in GenerateRoutes(). Or should I, since martini is handling all my requests
}
链接我已经提到:
答案 0 :(得分:2)
对于进行依赖注入,要测试的东西需要有一些方法来接收它的依赖项。在您的代码中,与mongodb的连接是在事物的初始化中完成的,以测试自身,什么不允许注入看起来像mongo连接的东西,同时作为模拟。
有很多方法可以实现它,但是最简单和最直接的方法之一是进行依赖注入,就是让它在测试时接受依赖注入,这样它的上下文就是配置依赖项的特定实现的位置。看看this example:
type DataStore interface {
Get(k string) string
Set(k, v string)
}
type MyInstance struct {
*martini.Martini
}
func NewAppInstance(d DataStore) *MyInstance {
...
}
func main() {
d := NewRedisDataStore("127.0.0.1", 6379)
NewAppInstance(d).Run()
}
实例需要Datastore
的实现才能工作,它不必知道有关其内部的任何信息,唯一重要的是它使用这两种方法实现接口{{ 1}}和Get
。实际上,作为单元测试的一般规则,您只想测试代码,而不是依赖项。在此示例中,它在&#34; production&#34;中使用Redis,但在测试中使用
Set
除了让框架检查它已被调用之外,它只是没有任何功能的东西。在测试本身中,您必须使用以下内容配置期望:
type MockedDataStore struct {
mock.Mock
}
func (m *MockedDataStore) Get(k string) string {
args := m.Called(k)
return args.String(0)
}
func (m *MockedDataStore) Set(k, v string) {
m.Called(k, v)
}
当然,用模拟的东西初始化实例,并测试它:
d := new(MockedDataStore)
...
d.On("Set", "foo", "42").Return().Once()
...
d.On("Get", "foo").Return("42").Once()
因此,作为总结,更具体地回答您的问题:
您需要使您的实例能够使用其依赖项进行初始化,例如:创建一个接收依赖项并返回实例的方法。然后模拟依赖关系,并从测试使用模拟而不是&#34;真实&#34;的。
使用d := new(MockedDataStore)
instance := NewAppInstance(d)
d.On("Get", "foo").Return("42").Once()
request, _ = http.NewRequest("GET", "/get/foo", nil)
response = httptest.NewRecorder()
instance.ServeHTTP(response, request)
d.AssertExpectations(t)
提供的方法ServeHTTP
生成对HTTP请求的响应,使用martini
来模拟响应的接收。当然,如果您的应用程序具有更复杂的功能,可以在HTTP接口之外使用,您也可以将其作为常规方法进行测试。