mongo_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. package tool
  2. import (
  3. "context"
  4. "fmt"
  5. "testing"
  6. "go.mongodb.org/mongo-driver/bson"
  7. "go.mongodb.org/mongo-driver/mongo/readpref"
  8. )
  9. // 配置测试用的 MongoDB 连接信息
  10. var cfg = Config{
  11. Uri: "mongodb://localhost:27017", // 请根据实际情况修改
  12. Database: "test",
  13. Username: "test",
  14. Password: "123456",
  15. }
  16. func TestInitMongo(t *testing.T) {
  17. // 调用 InitMongo 方法
  18. repo, err := InitMongo(cfg)
  19. if err != nil {
  20. t.Fatalf("InitMongo failed: %v", err)
  21. }
  22. defer func() {
  23. // 测试结束后断开连接
  24. err := repo.DB.Client().Disconnect(context.TODO())
  25. if err != nil {
  26. t.Errorf("Failed to disconnect from MongoDB: %v", err)
  27. }
  28. }()
  29. // 验证连接是否成功
  30. err = repo.DB.Client().Ping(context.TODO(), readpref.Primary())
  31. if err != nil {
  32. t.Errorf("Failed to ping MongoDB: %v", err)
  33. }
  34. // 验证数据库实例是否正确
  35. if repo.DB.Name() != cfg.Database {
  36. t.Errorf("Expected database name %s, but got %s", cfg.Database, repo.DB.Name())
  37. }
  38. }
  39. // TestInsertOne 测试 InsertOne 方法
  40. func TestInsertOne(t *testing.T) {
  41. // 初始化 MongoDB 连接,使用全局的 cfg
  42. repo, err := InitMongo(cfg)
  43. if err != nil {
  44. t.Fatalf("Failed to initialize MongoDB: %v", err)
  45. }
  46. defer func() {
  47. // 测试结束后断开连接
  48. err := repo.DB.Client().Disconnect(context.TODO())
  49. if err != nil {
  50. t.Errorf("Failed to disconnect from MongoDB: %v", err)
  51. }
  52. }()
  53. // 验证连接是否成功
  54. err = repo.DB.Client().Ping(context.TODO(), readpref.Primary())
  55. if err != nil {
  56. t.Fatalf("Failed to ping MongoDB: %v", err)
  57. }
  58. // 准备测试数据
  59. collectionName := "testCollection"
  60. testDocument := bson.M{
  61. "name": "Test User",
  62. "age": 25,
  63. "email": "test@example.com",
  64. }
  65. // 调用 InsertOne 方法
  66. result, err := repo.InsertOne(context.TODO(), collectionName, testDocument)
  67. if err != nil {
  68. t.Fatalf("InsertOne failed: %v", err)
  69. }
  70. // 验证插入结果
  71. if result.InsertedID == nil {
  72. t.Errorf("InsertedID is nil, insert may have failed")
  73. }
  74. // 验证文档是否实际插入到数据库
  75. var insertedDoc bson.M
  76. err = repo.DB.Collection(collectionName).FindOne(context.TODO(), bson.M{"_id": result.InsertedID}).Decode(&insertedDoc)
  77. if err != nil {
  78. t.Errorf("Failed to find inserted document: %v", err)
  79. }
  80. // 打印查询出来的插入数据
  81. fmt.Printf("查询到的插入数据: %+v\n", insertedDoc)
  82. // 清理测试数据
  83. _, err = repo.DB.Collection(collectionName).DeleteOne(context.TODO(), bson.M{"_id": result.InsertedID})
  84. if err != nil {
  85. t.Errorf("Failed to clean up test data: %v", err)
  86. }
  87. }
  88. func TestUpsert(t *testing.T) {
  89. // 使用全局 cfg 初始化 MongoDB 连接
  90. repo, err := InitMongo(cfg)
  91. if err != nil {
  92. t.Fatalf("Failed to initialize MongoDB: %v", err)
  93. }
  94. defer func() {
  95. // 测试结束后断开连接
  96. err = repo.DB.Client().Disconnect(context.TODO())
  97. if err != nil {
  98. t.Errorf("Failed to disconnect from MongoDB: %v", err)
  99. }
  100. }()
  101. // 验证连接是否成功
  102. err = repo.DB.Client().Ping(context.TODO(), readpref.Primary())
  103. if err != nil {
  104. t.Fatalf("Failed to ping MongoDB: %v", err)
  105. }
  106. collectionName := "testUpsertCollection"
  107. // 测试文档不存在时的 Upsert
  108. t.Run("Upsert when document does not exist", func(t *testing.T) {
  109. filter := bson.M{"name": "newUser"}
  110. update := bson.M{"$set": bson.M{"age": 25}}
  111. result, err := repo.Upsert(context.TODO(), collectionName, filter, update)
  112. if err != nil {
  113. t.Fatalf("Upsert failed: %v", err)
  114. }
  115. if result.MatchedCount != 0 {
  116. t.Errorf("Expected matched count 0, got %d", result.MatchedCount)
  117. }
  118. if result.ModifiedCount != 0 {
  119. t.Errorf("Expected modified count 0, got %d", result.ModifiedCount)
  120. }
  121. if result.UpsertedID == nil {
  122. t.Errorf("Expected non-nil upserted ID, got nil")
  123. }
  124. // 查询插入的文档
  125. var insertedDoc bson.M
  126. err = repo.DB.Collection(collectionName).FindOne(context.TODO(), bson.M{"_id": result.UpsertedID}).Decode(&insertedDoc)
  127. if err != nil {
  128. t.Errorf("Failed to find inserted document: %v", err)
  129. }
  130. // 打印插入的文档
  131. fmt.Printf("插入的文档: %+v\n", insertedDoc)
  132. // 清理测试数据
  133. _, err = repo.DB.Collection(collectionName).DeleteOne(context.TODO(), bson.M{"_id": result.UpsertedID})
  134. if err != nil {
  135. t.Errorf("Failed to clean up test data: %v", err)
  136. }
  137. })
  138. // 测试文档存在时的 Upsert
  139. t.Run("Upsert when document exists", func(t *testing.T) {
  140. // 先插入一个文档
  141. insertResult, err := repo.InsertOne(context.TODO(), collectionName, bson.M{"name": "existingUser", "age": 20})
  142. if err != nil {
  143. t.Fatalf("Failed to insert test document: %v", err)
  144. }
  145. filter := bson.M{"name": "existingUser"}
  146. update := bson.M{"$set": bson.M{"age": 30}}
  147. result, err := repo.Upsert(context.TODO(), collectionName, filter, update)
  148. if err != nil {
  149. t.Fatalf("Upsert failed: %v", err)
  150. }
  151. if result.MatchedCount != 1 {
  152. t.Errorf("Expected matched count 1, got %d", result.MatchedCount)
  153. }
  154. if result.ModifiedCount != 1 {
  155. t.Errorf("Expected modified count 1, got %d", result.ModifiedCount)
  156. }
  157. if result.UpsertedID != nil {
  158. t.Errorf("Expected nil upserted ID, got %v", result.UpsertedID)
  159. }
  160. // 查询更新后的文档
  161. var updatedDoc bson.M
  162. err = repo.DB.Collection(collectionName).FindOne(context.TODO(), bson.M{"_id": insertResult.InsertedID}).Decode(&updatedDoc)
  163. if err != nil {
  164. t.Errorf("Failed to find updated document: %v", err)
  165. }
  166. // 打印更新后的文档
  167. fmt.Printf("更新后的文档: %+v\n", updatedDoc)
  168. // 清理测试数据
  169. _, err = repo.DB.Collection(collectionName).DeleteOne(context.TODO(), bson.M{"_id": insertResult.InsertedID})
  170. if err != nil {
  171. t.Errorf("Failed to clean up test data: %v", err)
  172. }
  173. })
  174. }
  175. // TestNestedQuery 测试 NestedQuery 方法
  176. func TestNestedQuery(t *testing.T) {
  177. // 使用全局 cfg 初始化 MongoDB 连接
  178. repo, err := InitMongo(cfg)
  179. if err != nil {
  180. t.Fatalf("Failed to initialize MongoDB: %v", err)
  181. }
  182. defer func() {
  183. // 测试结束后断开连接
  184. err = repo.DB.Client().Disconnect(context.TODO())
  185. if err != nil {
  186. t.Errorf("Failed to disconnect from MongoDB: %v", err)
  187. }
  188. }()
  189. // 验证连接是否成功
  190. err = repo.DB.Client().Ping(context.TODO(), readpref.Primary())
  191. if err != nil {
  192. t.Fatalf("Failed to ping MongoDB: %v", err)
  193. }
  194. collectionName := "testNestedQueryCollection"
  195. // 准备测试数据
  196. testDocuments := []interface{}{
  197. bson.M{
  198. "name": "Alice",
  199. "address": bson.M{
  200. "city": "New York",
  201. "zip": "10001",
  202. },
  203. },
  204. bson.M{
  205. "name": "Bob",
  206. "address": bson.M{
  207. "city": "Los Angeles",
  208. "zip": "90001",
  209. },
  210. },
  211. }
  212. // 插入测试数据
  213. _, err = repo.DB.Collection(collectionName).InsertMany(context.TODO(), testDocuments)
  214. if err != nil {
  215. t.Fatalf("Failed to insert test documents: %v", err)
  216. }
  217. // 定义嵌套查询条件
  218. nestedFilter := bson.M{
  219. "address.city": "New York",
  220. }
  221. // 执行嵌套查询
  222. cursor, err := repo.NestedQuery(context.TODO(), collectionName, nestedFilter)
  223. if err != nil {
  224. t.Fatalf("NestedQuery failed: %v", err)
  225. }
  226. defer cursor.Close(context.TODO())
  227. // 遍历游标并验证结果
  228. var results []bson.M
  229. for cursor.Next(context.TODO()) {
  230. var result bson.M
  231. err = cursor.Decode(&result)
  232. if err != nil {
  233. t.Errorf("Failed to decode document: %v", err)
  234. continue
  235. }
  236. results = append(results, result)
  237. }
  238. if err = cursor.Err(); err != nil {
  239. t.Errorf("Cursor error: %v", err)
  240. }
  241. // 验证查询结果数量
  242. if len(results) != 1 {
  243. t.Errorf("Expected 1 result, got %d", len(results))
  244. }
  245. // 打印查询结果
  246. fmt.Printf("查询结果: %+v\n", results)
  247. // 验证查询结果内容
  248. if results[0]["name"] != "Alice" {
  249. t.Errorf("Expected name 'Alice', got %v", results[0]["name"])
  250. }
  251. // 清理测试数据
  252. _, err = repo.DB.Collection(collectionName).DeleteMany(context.TODO(), bson.M{})
  253. if err != nil {
  254. t.Errorf("Failed to clean up test data: %v", err)
  255. }
  256. }
  257. // 测试 QueryArrayContains 方法
  258. func TestQueryArrayContains(t *testing.T) {
  259. repo, err := InitMongo(cfg)
  260. if err != nil {
  261. t.Fatalf("Failed to initialize MongoDB: %v", err)
  262. }
  263. defer func() {
  264. if err := repo.DB.Client().Disconnect(context.TODO()); err != nil {
  265. t.Errorf("Failed to disconnect from MongoDB: %v", err)
  266. }
  267. }()
  268. collectionName := "testArrayContains"
  269. // 准备测试数据
  270. testDocuments := []interface{}{
  271. bson.M{"name": "doc1", "tags": []string{"apple", "banana"}},
  272. bson.M{"name": "doc2", "tags": []string{"cherry", "date"}},
  273. }
  274. // 插入测试数据
  275. _, err = repo.DB.Collection(collectionName).InsertMany(context.TODO(), testDocuments)
  276. if err != nil {
  277. t.Fatalf("Failed to insert test documents: %v", err)
  278. }
  279. // 执行查询
  280. elements := []interface{}{"apple"}
  281. cursor, err := repo.QueryArrayContains(context.TODO(), collectionName, "tags", elements)
  282. if err != nil {
  283. t.Fatalf("QueryArrayContains failed: %v", err)
  284. }
  285. defer cursor.Close(context.TODO())
  286. // 验证结果
  287. var results []bson.M
  288. for cursor.Next(context.TODO()) {
  289. var result bson.M
  290. if err := cursor.Decode(&result); err != nil {
  291. t.Errorf("Failed to decode document: %v", err)
  292. continue
  293. }
  294. results = append(results, result)
  295. }
  296. // 打印查询结果
  297. fmt.Printf("查询结果: %+v\n", results)
  298. if len(results) != 1 || results[0]["name"] != "doc1" {
  299. t.Errorf("Expected 1 result, got %d", len(results))
  300. }
  301. // 清理数据
  302. _, err = repo.DB.Collection(collectionName).DeleteMany(context.TODO(), bson.M{})
  303. if err != nil {
  304. t.Errorf("Failed to clean up test data: %v", err)
  305. }
  306. }
  307. func TestQueryArrayWithComplexFilter(t *testing.T) {
  308. repo, err := InitMongo(cfg)
  309. if err != nil {
  310. t.Fatalf("Failed to initialize MongoDB: %v", err)
  311. }
  312. defer func() {
  313. if err := repo.DB.Client().Disconnect(context.TODO()); err != nil {
  314. t.Errorf("Failed to disconnect from MongoDB: %v", err)
  315. }
  316. }()
  317. collectionName := "testArrayWithComplexFilter"
  318. // 准备测试数据
  319. testDocuments := []interface{}{
  320. bson.M{
  321. "name": "product1",
  322. "reviews": []bson.M{
  323. {"rating": 4, "author": "Alice"},
  324. {"rating": 2, "author": "Bob"},
  325. },
  326. },
  327. bson.M{
  328. "name": "product2",
  329. "reviews": []bson.M{
  330. {"rating": 1, "author": "Charlie"},
  331. {"rating": 3, "author": "David"},
  332. },
  333. },
  334. }
  335. // 插入测试数据
  336. _, err = repo.DB.Collection(collectionName).InsertMany(context.TODO(), testDocuments)
  337. if err != nil {
  338. t.Fatalf("Failed to insert test documents: %v", err)
  339. }
  340. // 定义复合筛选条件
  341. complexFilter := bson.M{
  342. "rating": bson.M{"$gte": 3},
  343. "author": "Alice",
  344. }
  345. // 执行查询
  346. cursor, err := repo.QueryArrayWithComplexFilter(context.TODO(), collectionName, "reviews", complexFilter)
  347. if err != nil {
  348. t.Fatalf("QueryArrayWithComplexFilter failed: %v", err)
  349. }
  350. defer cursor.Close(context.TODO())
  351. // 验证结果
  352. var results []bson.M
  353. for cursor.Next(context.TODO()) {
  354. var result bson.M
  355. if err := cursor.Decode(&result); err != nil {
  356. t.Errorf("Failed to decode document: %v", err)
  357. continue
  358. }
  359. results = append(results, result)
  360. }
  361. fmt.Printf("查询结果: %+v\n", results)
  362. if len(results) != 1 || results[0]["name"] != "product1" {
  363. t.Errorf("Expected 1 result, got %d", len(results))
  364. }
  365. // 清理数据
  366. _, err = repo.DB.Collection(collectionName).DeleteMany(context.TODO(), bson.M{})
  367. if err != nil {
  368. t.Errorf("Failed to clean up test data: %v", err)
  369. }
  370. }
  371. func TestQueryArrayElementByIndex(t *testing.T) {
  372. repo, err := InitMongo(cfg)
  373. if err != nil {
  374. t.Fatalf("Failed to initialize MongoDB: %v", err)
  375. }
  376. defer func() {
  377. if err := repo.DB.Client().Disconnect(context.TODO()); err != nil {
  378. t.Errorf("Failed to disconnect from MongoDB: %v", err)
  379. }
  380. }()
  381. // 验证连接
  382. if err := repo.DB.Client().Ping(context.TODO(), readpref.Primary()); err != nil {
  383. t.Fatalf("Failed to ping MongoDB: %v", err)
  384. }
  385. collectionName := "testQueryArrayElementByIndex"
  386. // 准备测试数据
  387. testDocuments := []interface{}{
  388. bson.M{
  389. "name": "doc1",
  390. "numbers": []int{10, 20, 30},
  391. },
  392. bson.M{
  393. "name": "doc2",
  394. "numbers": []int{40},
  395. },
  396. }
  397. // 插入测试数据
  398. _, err = repo.DB.Collection(collectionName).InsertMany(context.TODO(), testDocuments)
  399. if err != nil {
  400. t.Fatalf("Failed to insert test documents: %v", err)
  401. }
  402. // 按索引位置查询元素
  403. index := 1
  404. cursor, err := repo.QueryArrayElementByIndex(context.TODO(), collectionName, "numbers", index)
  405. if err != nil {
  406. t.Fatalf("QueryArrayElementByIndex failed: %v", err)
  407. }
  408. defer cursor.Close(context.TODO())
  409. // 验证结果
  410. var results []bson.M
  411. for cursor.Next(context.TODO()) {
  412. var result bson.M
  413. if err := cursor.Decode(&result); err != nil {
  414. t.Errorf("Failed to decode document: %v", err)
  415. continue
  416. }
  417. results = append(results, result)
  418. }
  419. if len(results) != 1 {
  420. t.Errorf("Expected 1 result, got %d", len(results))
  421. }
  422. // 清理数据
  423. _, err = repo.DB.Collection(collectionName).DeleteMany(context.TODO(), bson.M{})
  424. if err != nil {
  425. t.Errorf("Failed to clean up test data: %v", err)
  426. }
  427. }