unit-testing - 恐慌,因为参数必须是结构而不是接口,在 web.Router?
问题描述
在测试以下代码时:
package logHandler
import (
"ezsoft/apiserver_sdk/context"
"github.com/hsoshiant/web"
)
// Build simply builds a log handler router
//
// Parameters:
//
// - `mainRouter` : the main Router
//
// Returns:
//
// - a sub Router made specifically for logging
func Build(mainRouter *web.Router) *web.Router {
return mainRouter.Subrouter(context.Context{}, "/log").
Post("/", doLog)
}
我惊慌失措。context.Context
是这样定义的:
//BaseContext contains all the base context to be helpful when using the utilities
type BaseContext struct {
Session session.Store
ResponseWriter *web.ResponseWriter
RequestReader *web.Request
}
//Context contains all values needed when using the utilities
type Context struct {
BaseContext
JSONBody map[string]interface{}
tokenHandler *apiToken.APITokenHandlerSt
OAuthInstance *oAuth2.OAuth2St
}
考虑到可测试性/灵活性,开发人员编写了中间件函数 take context.ContextIntf
,它context.Context
实现了,定义如下:
//ContextIntf is the interface to use when using the context interface functions.
type ContextIntf interface {
SetUniversalHeaders(header map[string]string) map[string]string
GetInfo() *Context
GetOAuth() *oAuth2.OAuth2St
}
这是一个这样的中间件函数:
//AuthenticationMiddleware Middleware which handles all of the authentication.
func AuthenticationMiddleware(mw AuthenticationMiddlewareIntf, context context.ContextIntf, w web.ResponseWriter, r *web.Request, next web.NextMiddlewareFunc) {
//Check if the url should be public.
for _, url := range mw.GetInfo().nonAuthURLs {
if url.Method == r.Method && strings.Contains(r.URL.Path, url.DomainName) {
key := utilities.GetRemoteAdd(r) + ";" + r.URL.Path
if timeSince, ok := NonAuthSecurityMap[key]; ok {
var (
timeSinceTime, _ = time.Parse(time.UnixDate, timeSince)
timeSinceDuration = time.Since(timeSinceTime)
)
if timeSinceDuration < nonAuthTimeReset {
// will sleep for `nonAuthTimeReset` - `timeSinceDuration` > 0
time.Sleep(-(timeSinceDuration - nonAuthTimeReset))
}
}
NonAuthSecurityMap[key] = time.Now().Format(time.UnixDate)
next(w, r)
return
}
}
if errSt := CheckForAuthorization(mw, context, r, w); errSt != nil {
responses.Write(w, responses.Unauthorized(*errSt))
return
}
defer context.GetInfo().Session.SessionRelease(w)
next(w, r)
}
我不确定package web
正在检查哪些中间件业务功能,更不用说它们驻留在哪些业务包中,并且调用堆栈跟踪没有返回此类线索。
因此,我得到的错误是:
* You are adding a handler to a router with context type 'Context'
*
*
* Your handler function can have one of these signatures:
*
* // If you don't need context:
* func YourFunctionName(rw web.ResponseWriter, req *web.Request)
*
* // If you want your handler to accept a context:
* func (c *Context) YourFunctionName(rw web.ResponseWriter, req *web.Request) // or,
* func YourFunctionName(c *Context, rw web.ResponseWriter, req *web.Request)
*
* Unfortunately, your function has this signature: func(context.ContextIntf, web.ResponseWriter, *web.Request)
*
************************************************************************************************************************
为什么这请求一个Context
结构,而不是ContextIntf
它实现的那个?!
堆栈跟踪
看起来像这样:
goroutine 20 [running]:
testing.tRunner.func1(0xc04213e1e0)
C:/Go/src/testing/testing.go:742 +0x2a4
panic(0x7633c0, 0xc0421320a0)
C:/Go/src/runtime/panic.go:502 +0x237
github.com/hsoshiant/web.validateHandler(0x778420, 0x80d8f0, 0x13, 0x8405c0, 0x7b7960)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:286 +0x242
github.com/hsoshiant/web.(*Router).addRoute(0xc042106680, 0x7eeb93, 0x4, 0x7ee4bd, 0x1, 0x778420, 0x80d8f0, 0xc042051f80)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:223 +0x94
github.com/hsoshiant/web.(*Router).Post(0xc042106680, 0x7ee4bd, 0x1, 0x778420, 0x80d8f0, 0xc042106680)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:193 +0x6f
ezsoft/apiserver_sdk/logger/logHandler.Build(0xc0421064e0, 0xc042051f40)
D:/dev2017/GO/src/ezsoft/apiserver_sdk/logger/logHandler/handler.go:20 +0xcf
ezsoft/apiserver_sdk/logger/logHandler.TestBuild.func1(0xc04213e1e0)
D:/dev2017/GO/src/ezsoft/apiserver_sdk/logger/logHandler/handler_test.go:16 +0x91
testing.tRunner(0xc04213e1e0, 0x80d8e0)
C:/Go/src/testing/testing.go:777 +0xd7
created by testing.(*T).Run
C:/Go/src/testing/testing.go:824 +0x2e7
更新:它击中了私有方法doLog
,它是这样定义的:
func doLog(contextIntf context.ContextIntf, rw web.ResponseWriter, req *web.Request) {
var (
logType int = 0
code string = ""
message string = ""
context = contextIntf.GetInfo()
)
if val, OK := context.JSONBody["type"]; OK {
if val1, noErr := val.(float64); noErr {
logType = int(val1)
}
}
if logType == 0 {
responses.Write(rw, responses.FreeUnprocessableEntity("Type"))
return
}
if val, OK := context.JSONBody["code"]; OK {
if val1, noErr := val.(string); noErr {
code = val1
} else {
responses.Write(rw, responses.FreeUnprocessableEntity("Code"))
return
}
}
if val, OK := context.JSONBody["message"]; OK {
if val1, noErr := val.(string); noErr {
message = val1
}
}
if message == "" {
responses.Write(rw, responses.FreeUnprocessableEntity("message"))
return
}
if code > "" {
code = " (" + code + ") "
}
switch logType {
case 1:
logger.Instance.LogError(code + message)
case 2:
logger.Instance.LogWarning(code + message)
case 3:
logger.Instance.LogInfo(code + message)
default:
logger.Instance.LogWarning(code + message)
}
responses.Write(rw, responses.OK(0))
}
我仍然不明白为什么这个论点需要是 a context.Context
,或者我作为单元测试人员能做些什么。
解决方案
推荐阅读
- reactjs - 我是 React.js 的新手,这个错误是什么意思?(推动变量启动)
- python - 不和谐机器人用户反应
- iis - 无法在 IIS 上成功部署 Blazor 工作
- python - TypeError:参数 1 必须是 pygame.Surface,而不是 str,不知道是什么原因造成的
- android - 如何在使用自定义适配器实现的网格视图中添加 onItemClickListener()(这里我命名为 CategoryAdapter)
- nest - 如何使用基于多个术语的嵌套文档进行过滤?
- c - 函数“链接”的隐式声明;你的意思是“取消链接”吗?,函数“符号链接”的隐式声明
- variables - Ansible 变量插值在括号中不起作用
- java - 减小字节数组图像屏幕截图 selenium 的大小
- scala - 如何为以下只有一列的数据创建表