使用 gorilla/mux URL 参数的函数的单元测试

2024-02-02

TLDR:gorilla/mux 过去不提供设置 URL 变量的可能性。现在确实如此,这就是为什么第二高得票数的答案在很长一段时间内都是正确的答案。

原始问题如下:


这就是我想做的:

main.go

package main

import (
    "fmt"
    "net/http"
    
    "github.com/gorilla/mux"
)
    
func main() {
    mainRouter := mux.NewRouter().StrictSlash(true)
    mainRouter.HandleFunc("/test/{mystring}", GetRequest).Name("/test/{mystring}").Methods("GET")
    http.Handle("/", mainRouter)
    
    err := http.ListenAndServe(":8080", mainRouter)
    if err != nil {
        fmt.Println("Something is wrong : " + err.Error())
    }
}

func GetRequest(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    myString := vars["mystring"]
    
    w.WriteHeader(http.StatusOK)
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte(myString))
}

这将创建一个基本的 http 服务器侦听端口8080与路径中给出的 URL 参数相呼应。因此对于http://localhost:8080/test/abcd它将写回包含以下内容的响应abcd在响应正文中。

单元测试为GetRequest()函数在main_test.go :

package main

import (
    "net/http"
    "net/http/httptest"
    "testing"

    "github.com/gorilla/context"
    "github.com/stretchr/testify/assert"
)

func TestGetRequest(t *testing.T) {
    t.Parallel()
    
    r, _ := http.NewRequest("GET", "/test/abcd", nil)
    w := httptest.NewRecorder()

    //Hack to try to fake gorilla/mux vars
    vars := map[string]string{
        "mystring": "abcd",
    }
    context.Set(r, 0, vars)
    
    GetRequest(w, r)

    assert.Equal(t, http.StatusOK, w.Code)
    assert.Equal(t, []byte("abcd"), w.Body.Bytes())
}

测试结果是:

--- FAIL: TestGetRequest (0.00s)
    assertions.go:203: 
                        
    Error Trace:    main_test.go:27
        
    Error:      Not equal: []byte{0x61, 0x62, 0x63, 0x64} (expected)
                    != []byte(nil) (actual)
            
            Diff:
            --- Expected
            +++ Actual
            @@ -1,4 +1,2 @@
            -([]uint8) (len=4 cap=8) {
            - 00000000  61 62 63 64                                       |abcd|
            -}
            +([]uint8) <nil>
             
        
FAIL
FAIL    command-line-arguments  0.045s

问题是我如何伪造mux.Vars(r)用于单元测试? 我发现了一些讨论here https://groups.google.com/d/topic/gorilla-web/TKOE2I0116Y但所提出的解决方案不再有效。建议的解决方案是:

func buildRequest(method string, url string, doctype uint32, docid uint32) *http.Request {
    req, _ := http.NewRequest(method, url, nil)
    req.ParseForm()
    var vars = map[string]string{
        "doctype": strconv.FormatUint(uint64(doctype), 10),
        "docid":   strconv.FormatUint(uint64(docid), 10),
    }
    context.DefaultContext.Set(req, mux.ContextKey(0), vars) // mux.ContextKey exported
    return req
}

此解决方案不起作用,因为context.DefaultContext and mux.ContextKey不复存在。

另一个建议的解决方案是更改您的代码,以便请求函数也接受map[string]string作为第三个参数。其他解决方案包括实际启动服务器并构建请求并将其直接发送到服务器。在我看来,这将违背单元测试的目的,将它们本质上变成功能测试。

考虑到链接的线程是 2013 年的事实。还有其他选择吗?

EDIT

所以我读过gorilla/mux源代码,并根据mux.go功能mux.Vars()被定义为here https://github.com/gorilla/mux/blob/master/mux.go#L306像这样 :

// Vars returns the route variables for the current request, if any.
func Vars(r *http.Request) map[string]string {
    if rv := context.Get(r, varsKey); rv != nil {
        return rv.(map[string]string)
    }
    return nil
}

的价值varsKey定义为iota here https://github.com/gorilla/mux/blob/master/mux.go#L302。所以本质上,关键值是0。我编写了一个小型测试应用程序来检查这一点:main.go

package main

import (
    "fmt"
    "net/http"
    
    "github.com/gorilla/mux"
    "github.com/gorilla/context"
)
    
func main() {
    r, _ := http.NewRequest("GET", "/test/abcd", nil)
    vars := map[string]string{
        "mystring": "abcd",
    }
    context.Set(r, 0, vars)
    what := Vars(r)
        
    for key, value := range what {
        fmt.Println("Key:", key, "Value:", value)
    }

    what2 := mux.Vars(r)
    fmt.Println(what2)
    
    for key, value := range what2 {
        fmt.Println("Key:", key, "Value:", value)
    }

}

func Vars(r *http.Request) map[string]string {
    if rv := context.Get(r, 0); rv != nil {
        return rv.(map[string]string)
    }
    return nil
}

运行时输出:

Key: mystring Value: abcd
map[]
 

这让我想知道为什么测试不起作用以及为什么直接调用mux.Vars不起作用。


gorilla/mux提供了SetURLVars https://www.gorillatoolkit.org/pkg/mux#SetURLVars用于测试目的的函数,您可以使用它来注入您的模拟vars.

func TestGetRequest(t *testing.T) {
    r, _ := http.NewRequest("GET", "/test/abcd", nil)
    w := httptest.NewRecorder()

    //Hack to try to fake gorilla/mux vars
    vars := map[string]string{
        "mystring": "abcd",
    }

    // CHANGE THIS LINE!!!
    r = mux.SetURLVars(r, vars)
    
    GetRequest(w, r)

    assert.Equal(t, http.StatusOK, w.Code)
    assert.Equal(t, []byte("abcd"), w.Body.Bytes())
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 gorilla/mux URL 参数的函数的单元测试 的相关文章

  • 解组转义 XML

    在 Go 中 我将如何解码此 XML 响应 我尝试过建立一个自定义UnMarshal方法在我的Answerstruct 但我运气不太好
  • 为什么我不能将左大括号放在下一行?

    当我尝试编译以下代码时遇到奇怪的错误 package main import fmt fmt func main var arr 3 int for i 0 i lt 3 i fmt Printf d arr i 错误如下 unexpect
  • 与 Dagger 一起使用时,Espresso 生成 FileNotFoundException

    我一直在研究旧版 Android 应用程序 尝试为其添加测试和适当的架构 该应用程序有一个主要LaunchActivity它在启动时运行一系列检查 最初 该活动使用 Dagger 来 注入依赖项 活动将使用它来运行检查 但效果相当糟糕 我转
  • PrivateObject 找不到属性

    我的结构基本上如下所示 abstract class A protected string Identificator get set private void DoSomething DoSomethingSpecific protect
  • Spark scala 模拟 Spark.implicits 用于单元测试

    当尝试使用 Spark 和 Scala 简化单元测试时 我使用 scala test 和mockito scala 以及mockito Sugar 这只是让你做这样的事情 val sparkSessionMock mock SparkSes
  • 寻找网站测试自动化的方法

    我们开发定制调查网站 我正在寻找一种方法来自动化这些网站的模式测试 调查通常包含许多复杂的规则和分支 这些规则和分支也会根据项目的响应方式而触发 所有调查在发布给客户之前都经过严格测试 此测试需要大量的手动工作 我想了解一些可以通过回答问题
  • 如何在 Linux 中编写文本模式 GUI? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 当我编写脚本 程序时 我经常想弹出一个简单的文本 gui 来提示输入 我该怎么做 例如 来自 Shel
  • 单元测试报告的 XML 格式规范(DTD、XSD..)

    许多工具为单元测试报告生成和使用相同的 XML 文件格式 例子 source http junitpdfreport cvs sourceforge net junitpdfreport src resources examples tes
  • FakeAsync/tick (Async/whenStable) 与 detectorChanges()

    您能帮我区分这两件事吗 根据我的理解 如果你只使用 observable 你可以使用 detectorChanges 因此 您可以直接更改组件属性或监视服务调用并返回可观察的值 然后调用 detectorChanges 更改将在 html
  • 有队列实现吗?

    任何人都可以建议使用 Go 容器来实现简单快速的 FIF 队列 Go 有 3 种不同的容器 heap list and vector 哪一种更适合实现队列 事实上 如果您想要的是一个基本且易于使用的 fifo 队列 slice 可以满足您所
  • 如何在golang中创建一个充满“000000...”数据的10MB文件?

    我打算在日志或磁盘队列等系统中使用 fdatasync 首先是在 ext4 等文件系统中创建一个带有 000000 的 10MB 文件 但我不知道如何正确地做到这一点 jnml fsc r630 src tmp SO 16797380 ls
  • 什么是适合 Rails 3 的测试框架?

    去年我一直在使用 Ruby On Rails 但是 无法进行单元测试 现在我必须编写单元测试代码 哪个测试框架好 为什么 有这方面的好的教程吗 我的系统配置 Ruby 1 9 2 Rails 3 Ubuntu 10 第一个技巧是 尝试升级到
  • 模拟对象 - 将所有方法声明为虚拟方法还是使用接口?

    与 Java 不同 net 中的方法默认不是虚拟的 为了使用大多数模拟对象框架 您要么必须将要在模拟上使用的方法标记为 真实 对象上的虚拟方法 要么必须有一个可以模拟被测试类将使用的接口接受代替执行 将每个方法标记为虚拟似乎是一种不好的形式
  • 如何断言 Unittest 上的可迭代对象不为空?

    向服务提交查询后 我会收到一本字典或一个列表 我想确保它不为空 我使用Python 2 7 我很惊讶没有任何assertEmpty方法为unittest TestCase类实例 现有的替代方案看起来并不正确 self assertTrue
  • 如何同时使用 LoadHTMLGlob 和 LoadHTMLFiles

    我想要来自不同子目录的分隔符逻辑模板templates文件夹 下面是我的templates文件夹 templates authentication login gohtml logout gohtml index gohtml profil
  • 序列化对象以进行单元测试

    假设在单元测试中我需要一个对象 其中所有 50 个字段都设置了一些值 我不想手动设置所有这些字段 因为这需要时间而且很烦人 不知何故 我需要获得一个实例 其中所有字段都由一些非空值初始化 我有一个想法 如果我要调试一些代码 在某个时候我会得
  • 如何在 React 中测试表单提交?

    我有以下 React 组件 export default class SignUpForm extends React Component doSignupForm event Some API call render return div
  • 在 Go 中,如何将结构体转换为字节数组?

    我有一个我定义的结构实例 我想将其转换为字节数组 我尝试了 byte my struct 但这不起作用 另外 我还被指出二进制包 http golang org pkg encoding binary 但我不确定我应该使用哪个函数以及应该如
  • 如何使用 jest 模拟第三方库

    我正在开发一个node js应用程序使用nestjs我有一堂课叫LoggerService如下 export class LoggerService private logger Rollbar constructor this logge
  • 任务并行库周围是否有一个接口包装器,以便我可以将其交换用于单元测试?

    I asked 这个问题 https stackoverflow com questions 3362734 unit testing concurrent software what do you do不久以前 我现在知道这是一个坏主意

随机推荐

  • 如何在我的应用程序中显示网页?

    我需要从服务器端发送简单网页 带有图像 mht 或压缩网页文件夹 并在没有浏览器控制的情况下将其显示在我的 Android 应用程序的 UI 上 有人可以建议我如何在 Android 设备上继续执行此操作 要在应用程序中显示网页 有两种方法
  • 通过 POST 抓取 Bandcamp 粉丝收藏

    我一直在尝试抓取 Bandcamp 粉丝页面以获取他们购买的专辑列表 但我在有效地做到这一点时遇到了困难 我用 Selenium 写了一些东西 但它有点慢 所以我想学习一个解决方案 可以向网站发送 POST 请求并从那里解析 JSON 这是
  • 在 R 中打印 h2o 模型的“漂亮”表格

    有多个包用于R这有助于从统计模型输出中打印 漂亮 表格 LaTeX HTML TEXT 并轻松比较替代模型规范的结果 其中一些包是apsrtable xtable memisc texreg outreg and stargazer 示例请
  • 装饰器将函数状态从方法更改为函数

    更新 回答下面的内联问题 我有一个检查程序 一个目标是装饰器中的逻辑知道它正在装饰的函数是类方法还是常规函数 这以一种奇怪的方式失败了 以下是在 Python 2 6 中运行的代码 def decorate f print decorato
  • 使用 MapKit 将视图居中到用户位置的按钮

    MapKit 中是否有一个专用按钮可以将相机置于用户位置的中心 或者我是否必须手动创建按钮和切换mapView showsUserLocation true 这种方式运行良好 Swift 并且可以自定义按钮 class YourViewCo
  • Git 切换分支

    git 有一些东西我还没有搞懂 是分支 假设我有一个本地存储库A我从远程克隆的B 所以现在A检查主分支 所以当我从A它去B master B只是 github 上的一个克隆 C 为了保持同步 我时不时地从其他地方拉取C主分支 But now
  • 向 pentaho design studio 添加 jdbc 驱动程序并配置数据源

    我刚刚将 pentaho 的设计工作室集成到 BI 服务器中 有谁知道如何添加 mysql jdbc 驱动程序 我需要连接才能定义关系操作流程 在我的研究中我发现 http wiki bizcubed com au xwiki bin vi
  • js-bson 错误 - OpenShift 上的 Mosca(MQTT 代理)

    我一直在 OpenShift 上使用 NodeJS 进行一些工作 当我尝试在 Node 实例中运行 Mosca 服务器时遇到问题 我收到的错误如下 Error var lib openshift 5547bd284382ec394a0000
  • 获取Oracle子查询中order by后的第一行

    我有一个表学生 id 姓名 部门 年龄 分数 我想找到每个部门得分最高 在最年轻的学生中 的最年轻的学生 在 SQL Server 中 我可以使用以下 SQL select from student s1 where s1 id in se
  • 我应该避免 typedef,尝试使用原始名称并尽可能进行强制转换吗?

    我不确定这里的词汇 但希望我能让人理解 当我使用不太扎实的 C 知识来研究 winapi 时 我发现了很多 typedef 的东西 对我来说 这些东西似乎使问题变得过于复杂 并添加了我必须记住的另一件事 例如 UINT代替unsigned
  • 在python中创建用户定义类的对象集

    table set class GlobeLearningTable object def init self mac port dpid self mac mac self port port self dpid dpid def add
  • Android:动态创建控件和方向变化

    目前我正在开发一个动态创建控件的 Android 应用程序 每次用户单击按钮时 按钮下方都会出现一个新的 EditText 并且用户可以与 EditText 进行交互 但是 如果屏幕方向发生变化 用户创建的 EditText 也会消失 用户
  • 来自plotly的三元图

    在此输入图像描述 https i stack imgur com lyUJu png 我想在三元图中添加线条 水平 垂直 以突出显示某些部分 可以帮我吗 三元图 代码如下 fig px scatter ternary df a df a b
  • 根据 big-o 表示法进行评级的算法是否会受到并行性的影响?

    我刚刚读了一篇关于矩阵乘法突破的文章 O n 2 373 的算法 但我猜矩阵乘法是可以并行化的 那么 如果我们开始生产千核处理器 这会变得无关紧要吗 事情会发生怎样的变化 并行执行不会改变特定算法的复杂性的基本原理 充其量 您只是花费一些给
  • 验证模型属性 WCF Web APi

    我有一组使用 WCF Web Api 托管的服务 我需要做的是验证应用程序模型内的属性 例如 在 MVC 3 中 我像这样装饰模型中的属性 StringLength 30 public string UserName get set 然后在
  • 如何计算SQL中不同项目的数量

    数据库结构 Clubs ID ClubName Teams ID TeamName ClubID Players ID Name Registrations PlayerID TeamID Start date End date Seaso
  • 计算 GPU 上的彩色像素 - 理论

    我有一张 128 x 128 像素的图像 它被分解为 8 x 8 的网格 每个网格块包含 16 x 16 像素 要求 我想计算我的图像包含多少个黑色像素 直接的方法 I could通过逐行 逐列检查整个图像并检查像素是否为黑色来实现此目的
  • 如何编译 ast.Expr?

    import ast code 1 1 expr ast parse code body 0 print type expr compile ast Expression expr string eval gets me class ast
  • Rails + Amazon RDS:延迟问题

    我有一个应用程序 其数据库正在迁移到亚马逊RDS 由于 RDS 和我们的服务器之间的查询延迟 例如仅由于查询而导致加载时间长达 30 秒 我的性能显着下降 没有显式缓存 并且请求可以进一步优化 但这仍然比本地数据库慢 10 倍以上 这种业绩
  • 使用 gorilla/mux URL 参数的函数的单元测试

    TLDR gorilla mux 过去不提供设置 URL 变量的可能性 现在确实如此 这就是为什么第二高得票数的答案在很长一段时间内都是正确的答案 原始问题如下 这就是我想做的 main go package main import fmt