Edited at

sinon.jsでオブジェクトの中のDBのconnection.queryをstubする

More than 5 years have passed since last update.

オブジェクトの中でdbのconnectionを利用していて、そのオブジェクトのテストをするときにstubしようと思ってもtestコードからオブジェクトの中のconnectionには触れません。

具体的にはこんな感じ

mysql = require 'mysql'

config =
host: "localhost"
database: "sample"
user: "user"
password: "pass"

class DataTouchModel
constructor: (@config)->
con: ->
@_con ||= mysql.createConnection(@config)
getSomeData: (id)->
@con().query "SELECT * FROM bandits WHERE id = ?", [id], @processSomeData
processSomeData: (err, rows)->
console.log err, rows
model = new DataTouchModel(config)

で、このgetSomeDataのテストをしたいんだけど、dbにそれようのサンプルを入れるのは面倒です。

こういった場合には次のようにするとなんとかstubすることができます。

sinon = require 'sinon'

stub = sinon.stub(
# [2014/10/28修正] require('./node_modules/mysql/lib/Connection').prototype, 'query')
require('mysql/lib/Connection').prototype, 'query')

stub.withArgs(
"SELECT * FROM sample WHERE id = ?",
[0],
DataTouchModel.prototype.processRows).returns(null, ["myvalue"])
model = new DataTouchModel(config)
model.getSomeData(0)

# => null, ["myvalue"]

ポイントは、queryに渡す引数を必ず名前付きのメソッドにすることです。[demoId]のArrayは同じものとして扱ってくれますが、functionは違うものになるためです。

それか、.withArgsを除外して、直前で回数を指定して.retunrsを明記するかになるかと思います。


まとめ

中に入り込んでても、node_modulesまでほっくりかえせばなんとかなるよ!


  • これがいいのかどうかさっぱりわからないので、 @kyo_ago さんあたりに伺いたいと思っております。