ãã¤ã³ãã·ã¹ãã (6) -- Message Expectation
2013/10/04
ååã®æ«å°¾ã§ã次ã¯ã¹ãã¤ã«ã¤ãã¦æ¸ãã¾ããã¨äºåããã®ã§ãããæ¹ãã¦ããããã¨èª¿ã¹ã¦ã¿ãã¨ç§ãæã£ã¦ããã®ã¨éã£ã¦ãã¦ã話ããã¾ãã¾ã¨ã¾ãããããªããã¨ãåãã£ã¦ãã¾ãããè£ é£¾ã«ä½¿ãã¹ãã¤ã®åçãé¸ãã§ãã£ãã®ã§é常ã«æ®å¿µã§ãããä»åã¯è¦éããã¨ã«ãã¾ãã
ReceptionDesk
ã¯ã©ã¹ã®è²¬ä»»
ååããæ®ã課é¡ãã¨ãã¦ãReceptionDesk#sign_in
ã®ãã¹ãã RewardManager
ã¯ã©ã¹ã®æ¯ãèãã«ä¾åãã¦ãããããRewardManager
ã¯ã©ã¹ã®ä»æ§å¤æ´ã«ãã£ã¦ãã¹ããè½ã¡ãããã«ãªãå¯è½æ§ãããç¹ãææãã¾ããã
åé¡ã®ã¨ã°ã¶ã³ãã«ã®ã³ã¼ãã¯æ¬¡ã®éãã§ãï¼
specify 'ãã°ã¤ã³ã«æåããã¨ãã¦ã¼ã¶ã¼ã®ä¿æãã¤ã³ãã1å¢ãã' do expect { ReceptionDesk.new(customer.username, 'correct_password').sign_in }.to change { customer.points }.by(1) end
ããããéçºãé²ãã§ãåææ¥ãã°ã¤ã³ããã¨é常ã®ãã°ã¤ã³ãã¤ã³ãã¯å¥ã«2ãã¤ã³ãå ç®ããããã¨ããä»æ§ãå®è£ ãããã¨ãææ¥ã«ãã£ã¦ãã¹ããæåããã失æãããããããã«ãªãã¾ãã
ãã®ãããªç¶æ ã®ãã¹ããããå£ãããã(fragile)ãã¨å½¢å®¹ãã¾ãã
å®ã¯ãå ã»ã©ã®ã¨ã°ã¶ã³ãã«ã®èª¬ææã次ã®ããã«è¨ãæããã°ãåé¡ã解決ãã¾ãï¼
specify 'ãã°ã¤ã³ã«æåããã¨ãRewardManager#grant_login_pointsãå¼ã°ãã'
ãã®æã¯ãRewardManager
ã¯ã©ã¹ã®ä»æ§ã«é¢ããã常ã«çã§ãã
çµå±ã®ã¨ããããã°ã¤ã³ãã¤ã³ããä»ä¸ãããä»ä¸ããªãããä½ãã¤ã³ãä»ä¸ããã®ãã¯ãRewardManager
ã¯ã©ã¹ãé¢åãè¦ã¦ããã¾ããåä»ä¿ã¨ãã¦ã¯ RewardManager
ã«ãã客æ§ã«ãã°ã¤ã³ãã¤ã³ãããåºããã¦ï¼ãã¨ä¼ããã°è²¬ä»»ãæããããã¨ã«ãªãã¾ãã
Message Expectation
è¨ãæãå¾ã®æã RSpec ã®ã¨ã°ã¶ã³ãã«ã¨ãã¦è¡¨ç¾ããã¨ã次ã®ããã«ãªãã¾ãï¼
specify 'ãã°ã¤ã³ã«æåããã¨ãRewardManager#grant_login_pointsãå¼ã°ãã' do expect_any_instance_of(RewardManager).to receive(:grant_login_points) ReceptionDesk.new(customer.username, 'correct_password').sign_in end
1è¡ç®ãä¸è¬çã«æ¸ãç´ãã¨æ¬¡ã®ããã«ãªãã¾ãï¼
expect_any_instance_of(X).to receive(:y)
ã¯ã©ã¹ X
ã®ä»»æã®ã¤ã³ã¹ã¿ã³ã¹ã® :y
ã¡ã½ãããå¼ã°ãããã¨ããæå³ã§ãããªãããã㧠receive
ã¨ããã¡ã½ããã使ããã¦ããã®ã§ãããããRuby ã§ã¯ããªãã¸ã§ã¯ããããªãã¸ã§ã¯ãã«ã¡ãã»ã¼ã¸ãéããããã¨ããæ¯å©ã§ã¡ã½ããã³ã¼ã«ã表ç¾ãã¾ããã¤ã¾ããã¯ã©ã¹ X
ã®ä»»æã®ã¤ã³ã¹ã¿ã³ã¹ã :y
ã¨ããã¡ãã»ã¼ã¸ããåãåãï¼receiveï¼ããã¨ããæå¾
ããï¼expectï¼ãã®ã§ãã
ãã®ããã«ããããªãã¸ã§ã¯ããç¹å®ã®ã¡ãã»ã¼ã¸ãåãåããã¨ãäºåã«å®£è¨ããã¿ã¤ãã®ãã¹ãããMessage Expectationãã¨å¼ã³ã¾ãã
ãã®ã¿ã¤ãã®ãã¹ãã¯ãé常ã®ãã¹ãã¨ã¯æ¸ãæ¹ãç°ãªãã¾ãã
é常ã®ãã¹ãã§ã¯ã
do_something expect(object).to ...
ã®ããã«ããã¹ãã®å¯¾è±¡ã¨ãªã£ã¦ããã³ã¼ãï¼do_something
ï¼ãå®è¡ããå¾ã«ãã®ã³ã¼ãã®çµæã調ã¹ãã®ã§ããããMessage Expectationãã®å ´åã¯ã
expect(object).to receive(:a_method) do_something
ã®ããã«ããã¹ãã®å¯¾è±¡ã¨ãªã£ã¦ããã³ã¼ããå®è¡ããåã«ãç¹å®ã®ã¡ã½ããå¼ã³åºãã®æç¡ã«ã¤ãã¦å®£è¨ããã®ã§ãã
ä¸è¬ç㪠Message Expectation ã®æ¸ãæ¹
RSpec ã«ã¯æ§ã 㪠Message Expectation ã®æ¸ãæ¹ãç¨æããã¦ãã¾ãããã¨ããããã¯æ¬¡ã®4種é¡ãè¦ãã¦ããã°ååã§ãï¼
expect(x).to receive(:y)
expect(x).not_to receive(:y)
expect_any_instance_of(X).to receive(:y)
expect_any_instance_of(X).not_to receive(:y)
ååã®2ã¤ã§ã¯ x
ãä»»æã®ãªãã¸ã§ã¯ãï¼ã¯ã©ã¹ãå«ãï¼ã表ãã¾ãããã®ãªãã¸ã§ã¯ãã :y
ã¨ããã¡ãã»ã¼ã¸ãåãåããåãåããªããã宣è¨ãã¾ãã
å¾åã®2ã¤ã§ã¯ X
ãä»»æã®ã¯ã©ã¹ã表ãããã®ã¯ã©ã¹ã®ä»»æã®ã¤ã³ã¹ã¿ã³ã¹ã :y
ã¨ããã¡ãã»ã¼ã¸ãåãåããåãåããªããã宣è¨ãã¾ãã
ä¾ãã° RewardManager#grant_login_points
ãå¼ã°ããªããã¨ã表ç¾ããã«ã¯ã次ã®ããã«æ¸ãã¾ãï¼
expect_any_instance_of(RewardManager).not_to receive(:grant_login_points)
ReceptionDesk#sign_in
ã®ã¨ã°ã¶ã³ãã«ã°ã«ã¼ãã®æ«å°¾ã«æ¬¡ã®ã³ã¼ããå ãã¦ãã ããï¼
specify 'ãã°ã¤ã³ã«å¤±æããã¨ãRewardManager#grant_login_pointsã¯å¼ã°ããªã' do expect_any_instance_of(RewardManager).not_to receive(:grant_login_points) ReceptionDesk.new(customer.username, 'wrong_password').sign_in end
次åã¯
ReceptionDesk#sign_in
ã®ãã¹ãã«ã¯ã¾ã æ¹åã®ä½å°ãããã¾ãã次åã¯ãcontext
ã¡ã½ããã®ä½¿ãæ¹ã«ã¤ãã¦èª¬æãã¾ãï¼æ°ãå¤ãããªããã°ï¼ãã§ã¯ãã¾ãã
è£éº (2013-10-08)
RSpec Mocks ãªãã¸ããªã® Issue #336 ã§ã主è¦ã³ããã¿ã¼ã§ãã Myron Marston ããany_instance
ã®ä½¿ç¨ã¯æªãå
åï¼code smellï¼ãªã®ã§ãRSpec 3.0 ã§ã¯ããã©ã«ãã§ç¡å¹ã«ãã¦ã¯ã©ãããã¨ææ¡ãã¦ãã¾ãã
ç¾æç¹ã§ã¯çµè«ã¯åºã¦ããããæ©æ¥ã« any_instance
ã expect_any_instance_of
ã使ããªããªãå¯è½æ§ã¯ä½ãã¨æããã¾ãããå¾è´ã«å¤ããè°è«ã§ãã
å
ã»ã©ã® Issue ã§ã¯ããªã any_instance
ã®ä½¿ç¨ããæªãå
åããªã®ãã¯æ確ã«èª¬æããã¦ãã¾ãããããããããã¯ãããã¯ã©ã¹ã®ä»»æã®ã¤ã³ã¹ã¿ã³ã¹ãã§ã¯å¯¾è±¡ãåºãããã¨ãããã¨ã§ãã
ã¯ã©ã¹ X
ã®ã¤ã³ã¹ã¿ã³ã¹ã¯ã¢ããªã±ã¼ã·ã§ã³ã®ã©ãã§ã§ããä½åã§ãçã¾ããå¯è½æ§ãããã¾ãããã®ãã¡ã®1ã¤ãããã¡ãã»ã¼ã¸ãåãããã©ããã調ã¹ã¦ãå³å¯ãªãã¹ãã¨ã¯è¨ããªããã¨ãããã¨ã§ã¯ãªããã¨æããã¾ãã
ã§ã¯ãany_instance
ã使ããã«æ¸ãã¨ã©ããªãã§ããããã次ã®ã¨ã°ã¶ã³ãã«ã¯æ¸ãæãåã§ãï¼
specify 'ãã°ã¤ã³ã«æåããã¨ãRewardManager#grant_login_pointsãå¼ã°ãã' do expect_any_instance_of(RewardManager).to receive(:grant_login_points) ReceptionDesk.new(customer.username, 'correct_password').sign_in end
æ¸ãæãå¾ã¯æ¬¡ã®ããã«ãªãã¾ãï¼ããã¤ãæ¬é£è¼ã§èª¬æãã¦ããªãã¡ã½ããã使ç¨ãã¦ãã¾ãï¼ï¼
specify 'ãã°ã¤ã³ã«æåããã¨ãRewardManager#grant_login_pointsãå¼ã°ãã' do reward_manager = double RewardManager.stub(:new).with(customer).and_return(reward_manager) expect(reward_manager).to receive(:grant_login_points) ReceptionDesk.new(customer.username, 'correct_password').sign_in end
ããããã°ãç¹å®ã®ãªãã¸ã§ã¯ã customer
ãå¼æ°ã«ãã¦ã¤ã³ã¹ã¿ã³ã¹åããã RewardManager
ãªãã¸ã§ã¯ãã®ã¿ã対象㫠grant_login_points
ã¡ã½ãããå¼ã³åºããããã©ããã調ã¹ããã¾ãã
æ¸ãæãã«ãã£ã¦ãã¹ãã¯ããå³å¯ã«ãªãã¾ãããããã¹ãã³ã¼ãã®éã¯ããªãå¢ãã¦ãã¾ããå³å¯ããåãããç°¡æ½ããåãããè¿·ãã¨ããã§ãã
ç¾æç¹ã§ã¯ãä¸è¨ã®ãããªã¨ã°ã¶ã³ãã«ã§ã¯ any_instance
ã使ã£ã¦ãããã®ã§ã¯ãªããã¨ç§ã¯èãã¦ãã¾ããããããã¾ã çµè«ã¯åºã¦ãã¾ããã