オブジェクトの中で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 さんあたりに伺いたいと思っております。