使用Docker和Golang进行便捷的MongoDB测试

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: 本文讲的是使用Docker和Golang进行便捷的MongoDB测试,【编者的话】Docker的使用场景之一就是测试,在测试中,我们有时候会由于超时或者仅仅因为两个开发版本使用相同的数据库在同时运行而导致测试出错。
本文讲的是使用Docker和Golang进行便捷的MongoDB测试 【编者的话】Docker的使用场景之一就是测试,在测试中,我们有时候会由于超时或者仅仅因为两个开发版本使用相同的数据库在同时运行而导致测试出错。本文以Golang和MongoDB为例,介绍了如何使用Docker来简化和改进单元测试。

背景
我们正在不断寻找新技术来解决开发中遇到的问题。我们一直在使用Java+Spring,然而Java 8和Spring Boot为我们带来了新的生机,并改变了单一的Java应用为微服务模式(译者注:monolithic Java applications)。而当你有API的时候,你只需一个合适的前端框架就可以替代jsp和jQuery:在我们的案例中我们选择AngularJS。两年前我们第一次使用了Angular,现在所有的项目都引入了AngularJS。

超过10年的Java 在你的灵魂深处留下了深刻的印记
这两三年来,我一直在寻找更好的东西。在这个行业中,最好的事情是你会有各种选择。我们曾经使用NodeJS构建了几个项目,并学习了Ruby的服务配置管理框架Chef。当然我们也有一些Scala项目,并了解过Clojure、Haskell和Rust语言,后来我们发现了 Go 。虽然我们只使用Go语言编写了几个小服务,但是却对与Go相关的语言、标准库、工具和社区而震惊。有大量的博客文章解释了为什么不同的公司选择了Go,本文不再赘述。同时如果你想学习如何编写Go,可以查阅 A tour of Go ,如果你喜欢阅读请查看 Effective Go 或观看 A tour of Go 视频。

负载测试
可能我需要相当长的篇幅来介绍负载测试,所有的编程语言都需要编写单元测试代码,另外还有一些需要使用TDD方法和达到100%测试覆盖率的目标的方法。动态语言需要安排更多类型的测试,可能当你经过了上百次的测试,你的应用才能达到一个稳定的状态。痛苦的是,由于有不同的开发语言,所以你的测试需要很多的准备工作:曾经几秒钟就可以完成的事情,那现在可能会需要几分钟,甚至是几十分钟才能完成。因此,你要开始仓库(数据库)的调用,并建立集成测试的数据库开发的预载和清除方法。有时候集成测试可能会失败,而这可能是由于超时或者仅仅因为两个开发版本使用相同的数据库在同时运行。

使用Golang和Docker进行的测试
Golang不会有类似的问题,有了Golang的快速构建、测试周期和一些Docker魔法的支持,你能够在几秒内启动MongoDB Docker容器并运行所有的测试。这个真的是从开始到结束只需要几秒的时间,但是第一次运行除外,因为第一次运行的时候需要下载和提供MongoDB Docker容器。

我从这里得到真正的灵感,即使一直在寻找借口来确认这是否是正确的:

3AF91CF4-74A0-4577-98C9-ECE3FFE7C014.jpg


让我们做一些可以进行Docker实验的nice的事情
我已经研究Golang+AngularJS一段时间了,而且现在是最佳时间来证明Docker是否如宣传的一样神奇。对于OS X用户来说,涉及到Docker时会有个小烦恼:它只在Linux上面运行。是的,你可以运用Boot2Docker来安装到OS X上,而Boot2Docker将在虚拟化的Linux上运行Docker。我已经通过Ubuntu来使用Vagrant作为开发环境,因此我刚刚在这上面安装了Docker。

首先,我要熟悉Camlistore的实施环境并且复制它。特别感谢 Brad Fitzpartick ,你通过Camlistore和Golang标准程序库来完成了出色的工作。 Thanks!

可以通过 story_test.go 来找到实际测试。对于那些看不懂Golang的用户,我已经在最重要的代码部分添加了额外的注释。
Setup test environment
func TestStoryCreateAndGet(t *testing.T) {

// Start MongoDB Docker container
//
// One of the most powerful features in Golang
// is the ability to return multiple values from functions.
// In this we get:
// - containerID (type=ContainerID struct)
// - ip (type=string)
containerID, ip := dockertest.SetupMongoContainer(t)

// defer schedules KillRemove(t) function call to run immediatelly
// when TestStoryCreateAndGet(t) function is done,
// so you can place resource clenup code close to resource allocation
defer containerID.KillRemove(t)

app := AppContext{}

// Connect to Dockerized MongoDB
mongoSession, err := mgo.Dial(ip)

// Golang favors visible first hand error handling.
// Main idea is that Errors are not exceptional so you should handle them
if err != nil {
Error.Printf("MongoDB connection failed, with address '%s'.", Configuration.MongoUrl)
}

// close MongoDB connections when we're finished
defer mongoSession.Close()

app.mongoSession = mongoSession

// create test http server with applications route configuration
ts := httptest.NewServer(app.createRoutes())
defer ts.Close()

storyId := testCreate(ts, t) // run create test
testGet(ts, storyId, t) // run get test for created story
}

Post json document to http handler
func testCreate(ts *httptest.Server, t *testing.T) string {

postData := strings.NewReader("{\"text\":\"tekstiä\",\"subjectId\":\"k2j34\",\"subjectUrl\":\"www.fi/k2j34\"}")

// create http POST with postData JSON
res, err := http.Post(ts.URL+"/story", applicationJSON, postData)

// read http response body data
data, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
t.Error(err)
}

id := string(data)

// verify that we got correct http status code
if res.StatusCode != http.StatusCreated {
t.Fatalf("Non-expected status code: %v\n\tbody: %v, data:%s\n", http.StatusCreated, res.StatusCode, id)
}

// verify that we got valid lenght response data
if res.ContentLength != 5 {
t.Fatalf("Non-expected content length: %v != %v\n", res.ContentLength, 5)
}
return id
}

Test that previously created story exists
func testGet(ts *httptest.Server, storyId string, t *testing.T) {

// create http GET request with correct path
res, err := http.Get(ts.URL + "/story/" + storyId)
data, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
t.Error(err)
}

body := string(data)

// validate status code
if res.StatusCode != http.StatusOK {
t.Fatalf("Non-expected status code: %v\n\tbody: %v, data:%s\n", http.StatusCreated, res.StatusCode, body)
}

// validate that response has correct storyId
if !strings.Contains(body, "{\"storyId\":\""+storyId+"\",") {
t.Fatalf("Non-expected body content: %v", body)
}

// validate that content leght is what is should be
if res.ContentLength < 163 && res.ContentLength > 165 {
t.Fatalf("Non-expected content length: %v < %v, content:\n%v\n", res.ContentLength, 160, body)
}

}


眼见为实
因此,启动MongoDB Docker容器,将它配置到应用程序,然后用内置的测试直至创建HTTP服务器。然后,我们设置同样的路由给服务器,并对测试服务器运行两个请求,第一个来创建故事评论,另外一个来获取它。所有的数据都被存储了,并且从MongoDB中获取。那么所有这一切需要多久时间呢?

docker-testing-0d333fd6d1b21887e978d4d3110dc715.png

仅两秒以下!

docker-testing-with-race-detection-567c060af6235504c42111c3c5d33446.png

即使你运行一些条件选择器它仍只需要不到3秒 \o/

Docker是针对所有的用户,而不仅仅是Golang用户

对于那些可以使用Golang的用户,Docker也可以帮助你。它当然没有Golang那么快速,但是和使用外部的MongoDB服务器一样的快,而且没有额外的清理麻烦。毫无疑问,Docker是虚拟化业务中的游戏变化者,并且这些炒作也得到了很好的回报。这样就没有借口来针对MongoDB功能编写任何模拟测试。

原文链接:Painless MongoDB testing with Docker and Golang(翻译:吴锦晟 校对:李颖杰)

===============================================
译者介绍
吴锦晟 ,大连理工大学硕士研究生,就职于上海金桥信息股份有限公司技术中心。目前负责云计算、虚拟化、大数据及其信息可视化等方向的研究和应用。希望通过翻译技术文章于Dockone社区为Docker的步道做出微薄贡献。

原文发布时间为:2015-01-14
本文作者:吴锦晟 
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:使用Docker和Golang进行便捷的MongoDB测试
相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
2月前
|
存储 NoSQL 大数据
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
45 3
|
2月前
|
存储 NoSQL MongoDB
docker安装Mongodb
这篇文章详细说明了如何使用Docker安装MongoDB,包括拉取镜像、创建并运行容器、数据持久化存储以及访问容器内的MongoDB服务的具体步骤。
292 1
|
4月前
|
消息中间件 测试技术 RocketMQ
docker部署RockerMQ单机测试环境
docker部署RockerMQ单机测试环境
|
4月前
|
关系型数据库 MySQL 测试技术
使用docker部署MySQL测试环境
使用docker部署MySQL测试环境
58 0
|
4月前
|
分布式计算 大数据 Hadoop
最快方式搭建docker大数据 测试集群
【8月更文挑战第5天】快速搭建Docker大数据测试集群可采用预构建镜像与Compose文件、利用云服务如AWS的ECS、自动化工具如Ansible或参考在线教程。只需简单配置如内存分配及路径,运行`docker-compose up`即可启动含NameNode、DataNode等组件的Hadoop集群。根据需求与资源选择合适方法。
|
6月前
|
NoSQL MongoDB Docker
windows下基于docker安装mongodb
windows下基于docker安装mongodb
185 1
|
7月前
|
NoSQL 测试技术 MongoDB
【MongoDB 专栏】MongoDB 的性能基准测试与评估
【5月更文挑战第11天】MongoDB的性能基准测试对于优化至关重要,涉及数据读写速度、查询响应时间及吞吐量等指标。测试应明确目标和范围,选择合适的工具,考虑数据模型、索引、查询优化和系统配置等因素。性能评估需关注读写吞吐量、响应时间和资源利用率。通过多次测试、逐步增加负载和对比其他系统,识别性能瓶颈并持续优化。随着技术发展,测试方法和工具将持续创新,以应对复杂性能挑战。
309 3
【MongoDB 专栏】MongoDB 的性能基准测试与评估
|
7月前
|
网络安全 Docker 容器
测试开发环境下centos7.9下安装docker的minio
测试开发环境下centos7.9下安装docker的minio
300 1
|
7月前
|
NoSQL Unix MongoDB
【docker 】docker-compose 部署mongoDB
【docker 】docker-compose 部署mongoDB
239 1
|
6月前
|
IDE 前端开发 时序数据库
【Docker项目实战】使用Docker部署speedtest-tracker速度测试追踪器
【6月更文挑战第4天】使用Docker部署speedtest-tracker速度测试追踪器
490 0