如何定义模拟方法被调用零次
How to define that mock method gets invoked zero times
我正在尝试测试以下方法:
//AuthenticationMiddleware Middleware which handles all of the authentication.
func AuthenticationMiddleware(context context.ContextIntf, w web.ResponseWriter, r *web.Request, next web.NextMiddlewareFunc) {
//Check if url is one that doesn't need authorization. If not than send them to the login page.
for _, url := range AuthMWInstance.GetInfo().nonAuthURLs {
if url.Method == r.Method && strings.Contains(r.URL.Path, url.DomainName) {
next(w, r)
return
}
}
if errSt := CheckForAuthorization(context, r, w); errSt != nil {
responses.Write(w, responses.Unauthorized(*errSt))
return
}
defer context.GetInfo().Session.SessionRelease(w)
next(w, r)
}
在这种情况下,有一个 SessionRelease
被调用,当且仅当 r
包含一个需要授权的 URL,并且授权成功。
了解以下内容可能很重要:
type MiddlewareSt struct {
//NonAuthUrls URLs that can be accessed without a token.
nonAuthURLs []url.URLSt
}
type MiddlewareIntf interface {
GetInfo() *MiddlewareSt
CheckTokenAndSetSession(context context.ContextIntf, r *web.Request, w web.ResponseWriter,
token string, scope string, remoteAddr string) *errors.ErrorSt
}
var AuthMWInstance MiddlewareIntf
而 CheckForAuthorization
的 return 值最终取决于 AuthMWInstance
我的测试策略
- 创建一个存根中间件实例以将
AuthMWInstance
初始化为,即 returns nil
for CheckTokenAndSetSession
(当然,将会话设置抽象出来,以存根对象本身的创建,它有 Session
),和一个 MiddlewareSt
充满假 nonAuthURLs
for GetInfo()
- 创建一个模拟
session.Store
,对于除完整性测试之外的所有测试,期望对 SessionRelease
的调用为零。
可能值得注意(但假设)我正在使用 testify,mockery 库进行模拟和断言。
测试
是这样实现的:
func TestAuthenticationMiddleware(t *testing.T) {
// bring in the errors
sdkTesting.InitErrors()
// create/set up the test doubles
// mock session
sessionMock := new(testing_mock.MockStore)
// temporarily set AuthMWInstance to a stub
instance := AuthMWInstance
AuthMWInstance = &StubMiddlewareInstance{
Session: sessionMock,
}
// AuthMWInstance.Session
defer func() { AuthMWInstance = instance }()
// fake ResponseWriter
w := new(StubResponseWriter)
// fake web requests
requestWithoutAuth := new(web.Request)
requestWithoutAuth.Request = httptest.NewRequest("GET",
"http://example.com/logout",
nil,
)
// do tests here
t.Run("AuthorizationNotRequired", func(t *testing.T) {
// place expectations on sessionMock, namely that it does
// **not** invoke `SessionRelease`
sessionMock.On("SessionRelease", w).
Times(0)
AuthenticationMiddleware(new(context.Context),
w,
requestWithoutAuth,
web.NextMiddlewareFunc(func(web.ResponseWriter, *web.Request) {}))
sessionMock.AssertExpectations(t)
})
}
运行时行为
发生以下假失败:。就好像,而不是做:
sessionMock.On("SessionRelease", w).
Times(0)
,我是这样的:
sessionMock.On("SessionRelease", w).
Once()
注意 session.Store.SessionRelease
没有 return 任何东西,因此我什至懒得使用 Return()
。
我是在断言它被调用的次数正好是零次吗?
我觉得有点傻。
问题是我在为
烦恼
sessionMock.AssertExpectations(t)
当我可以简单地说
sessionMock.AssertNotCalled(t, "SessionRelease", w)
(关于该方法的文档 here)
执行后者解决了问题,并且完全按照我的意愿完成了。
我正在尝试测试以下方法:
//AuthenticationMiddleware Middleware which handles all of the authentication.
func AuthenticationMiddleware(context context.ContextIntf, w web.ResponseWriter, r *web.Request, next web.NextMiddlewareFunc) {
//Check if url is one that doesn't need authorization. If not than send them to the login page.
for _, url := range AuthMWInstance.GetInfo().nonAuthURLs {
if url.Method == r.Method && strings.Contains(r.URL.Path, url.DomainName) {
next(w, r)
return
}
}
if errSt := CheckForAuthorization(context, r, w); errSt != nil {
responses.Write(w, responses.Unauthorized(*errSt))
return
}
defer context.GetInfo().Session.SessionRelease(w)
next(w, r)
}
在这种情况下,有一个 SessionRelease
被调用,当且仅当 r
包含一个需要授权的 URL,并且授权成功。
了解以下内容可能很重要:
type MiddlewareSt struct {
//NonAuthUrls URLs that can be accessed without a token.
nonAuthURLs []url.URLSt
}
type MiddlewareIntf interface {
GetInfo() *MiddlewareSt
CheckTokenAndSetSession(context context.ContextIntf, r *web.Request, w web.ResponseWriter,
token string, scope string, remoteAddr string) *errors.ErrorSt
}
var AuthMWInstance MiddlewareIntf
而 CheckForAuthorization
的 return 值最终取决于 AuthMWInstance
我的测试策略
- 创建一个存根中间件实例以将
AuthMWInstance
初始化为,即 returnsnil
forCheckTokenAndSetSession
(当然,将会话设置抽象出来,以存根对象本身的创建,它有Session
),和一个MiddlewareSt
充满假nonAuthURLs
forGetInfo()
- 创建一个模拟
session.Store
,对于除完整性测试之外的所有测试,期望对SessionRelease
的调用为零。
可能值得注意(但假设)我正在使用 testify,mockery 库进行模拟和断言。
测试
是这样实现的:
func TestAuthenticationMiddleware(t *testing.T) {
// bring in the errors
sdkTesting.InitErrors()
// create/set up the test doubles
// mock session
sessionMock := new(testing_mock.MockStore)
// temporarily set AuthMWInstance to a stub
instance := AuthMWInstance
AuthMWInstance = &StubMiddlewareInstance{
Session: sessionMock,
}
// AuthMWInstance.Session
defer func() { AuthMWInstance = instance }()
// fake ResponseWriter
w := new(StubResponseWriter)
// fake web requests
requestWithoutAuth := new(web.Request)
requestWithoutAuth.Request = httptest.NewRequest("GET",
"http://example.com/logout",
nil,
)
// do tests here
t.Run("AuthorizationNotRequired", func(t *testing.T) {
// place expectations on sessionMock, namely that it does
// **not** invoke `SessionRelease`
sessionMock.On("SessionRelease", w).
Times(0)
AuthenticationMiddleware(new(context.Context),
w,
requestWithoutAuth,
web.NextMiddlewareFunc(func(web.ResponseWriter, *web.Request) {}))
sessionMock.AssertExpectations(t)
})
}
运行时行为
发生以下假失败:
sessionMock.On("SessionRelease", w).
Times(0)
,我是这样的:
sessionMock.On("SessionRelease", w).
Once()
注意 session.Store.SessionRelease
没有 return 任何东西,因此我什至懒得使用 Return()
。
我是在断言它被调用的次数正好是零次吗?
我觉得有点傻。
问题是我在为
烦恼sessionMock.AssertExpectations(t)
当我可以简单地说
sessionMock.AssertNotCalled(t, "SessionRelease", w)
(关于该方法的文档 here)
执行后者解决了问题,并且完全按照我的意愿完成了。