<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Test Doubles &#8211; Few Steps &#8211; ก้าวสั้นๆ แต่ไปเรื่อยๆ</title>
	<atom:link href="https://myifew.com/tag/test-doubles/feed/" rel="self" type="application/rss+xml" />
	<link>https://myifew.com</link>
	<description></description>
	<lastBuildDate>Tue, 17 Jul 2018 04:07:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://myifew.com/wp-content/uploads/2018/07/cropped-logo6-ts-32x32.png</url>
	<title>Test Doubles &#8211; Few Steps &#8211; ก้าวสั้นๆ แต่ไปเรื่อยๆ</title>
	<link>https://myifew.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>เมื่อ Unit Test ต้องทดสอบร่วมกับระบบอื่นๆ จะแก้ปัญหาอย่างไร?.. มารู้จัก Test Doubles กัน</title>
		<link>https://myifew.com/4556/how-to-skip-dependency-in-unit-test-by-test-doubles/</link>
					<comments>https://myifew.com/4556/how-to-skip-dependency-in-unit-test-by-test-doubles/#respond</comments>
		
		<dc:creator><![CDATA[iFew]]></dc:creator>
		<pubDate>Thu, 05 Jul 2018 18:21:41 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[Automation Testing]]></category>
		<category><![CDATA[Test Doubles]]></category>
		<category><![CDATA[Testable]]></category>
		<category><![CDATA[Unit Test]]></category>
		<guid isPermaLink="false">https://myifew.com/?p=4556</guid>

					<description><![CDATA[หลังจากเขียนเรื่อง Unit Test ไปก็หลายบล็อก ไล่ตั้งแต่เรื่องพื้นฐานอย่าง การออกแบบระบบให้รองรับการทดสอบ (Testable) มาจนถึง วิธีการคิดและลงมือทำ Automated Test ด้วย Unit Test และ รูปแบบการทดสอบของ Unit Test ก็ยังเหลือเรื่องหนึ่งที่สำคัญมากและหลายคนอาจจะสงสัยตอนที่ทำ Unit Test นั่นก็คือ "จะทำอย่างไร เมื่อสิ่งที่เราทดสอบ อย่าง Class, Function มันต้องไปทำงานร่วมกับสิ่งอื่นๆ เช่น Class อื่นๆ, Function อื่นๆ, Database, API ตัวอื่นๆ ของเรา หรือ API ภายนอกระบบ" ..]]></description>
										<content:encoded><![CDATA[<p>หลังจากเขียนเรื่อง Unit Test ไปก็หลายบล็อก ไล่ตั้งแต่เรื่องพื้นฐานอย่าง <a href="https://myifew.com/4414/design-project-code-structure-for-testable/">การออกแบบระบบให้รองรับการทดสอบ (Testable)</a> มาจนถึง <a href="https://myifew.com/4455/design-and-develop-code-for-testable/">วิธีการคิดและลงมือทำ Automated Test ด้วย Unit Test</a> และ <a href="https://myifew.com/4480/unit-test-solitary-or-sociable/">รูปแบบการทดสอบของ Unit Test</a> ก็ยังเหลือเรื่องหนึ่งที่สำคัญมากและหลายคนอาจจะสงสัยตอนที่ทำ Unit Test นั่นก็คือ &#8220;จะทำอย่างไร เมื่อสิ่งที่เราทดสอบ อย่าง Class, Function มันต้องไปทำงานร่วมกับสิ่งอื่นๆ เช่น Class อื่นๆ, Function อื่นๆ, Database, API ตัวอื่นๆ ของเรา หรือ API ภายนอกระบบ&#8221; ..<span id="more-4556"></span></p>
<h2>ทบทวน &#8220;5 คุณสมบัติของ Unit Test ที่ดี&#8221; อีกครั้ง</h2>
<p>ก่อนจะไปต่อ ขอทบทวนคุณสมบัติที่ดีของ Unit Test อีกรอบ ที่ควรจะต้องเป็นไปตาม<a href="http://www.somkiat.cc/good-unit-test-with-first/" target="_blank" rel="noopener">หลักการของ FIRST</a> คือ</p>
<ul>
<li><strong>Fast:</strong> ทำงานได้เร็ว</li>
<li><strong>Isolated:</strong> เป็นอิสระจากกัน</li>
<li><strong>Repeatable:</strong> ทำซ้ำได้ ไม่ขึ้นกับระบบอื่นๆ เช่น API ภายนอก, Database, File System</li>
<li><strong>Self-Verify:</strong> แสดงให้เห็นผลการทดสอบ ผ่าน หรือไม่ผ่านได้อย่างชัดเจน</li>
<li><strong>Timely:</strong> เขียนให้ถูกเวลา คือ ควรมี Test ก่อน เพื่อให้ได้เข้าใจปัญหา และจึงเขียนโค้ดเข้ามาแก้ปัญหานั้น</li>
</ul>
<p>คราวนี้ การที่ Unit Test ของเราต้องไปทำงานร่วมกับสิ่งอื่นๆ มันมักทำให้ขัดแย้งกับ 5 ข้อ ข้างต้น เช่น</p>
<ul>
<li>เมื่อเราต้องการทดสอบ Function ที่ต้องต่อกับ Database มันก็จะทำงานไม่เร็ว เพราะ Query นาน, มันทำซ้ำไม่ได้ เพราะต้องเพิ่มลบข้อมูลจาก Database ตลอด แล้วไหนจะกระทบตัวอื่นๆที่อาจจะใช้ Database เดียวกันด้วย</li>
<li>เมื่อเราต้องการทดสอบ Function ที่ต้องต่อกับ API ภายในของเราเอง หรือภายนอก มันก็ทำงานไม่เร็ว เพราะมีเรื่องของความเร็ว Network/Internet ซึ่งถ้า Internet ล่ม ก็ทำซ้ำไม่ได้ หรือถ้าส่งข้อมูลไปให้แล้วบาง API ก็ส่งข้อมูลซ้ำไม่ได้ เช่น ส่งข้อมูลไป API สมัครสมาชิกที่มีเงื่อนไขสมัครด้วยอีเมลเดียวเท่านั้น</li>
<li>เมื่อเราต้องการทดสอบ Function ที่ต้องไปทำงานร่วมกับ Function อื่น แต่มันยังทำไม่เสร็จหรือไม่ได้ทำ เราก็ทดสอบไม่ได้อยู่ดี</li>
</ul>
<p>ดังนั้น ถ้าต้องการให้ Unit Test ของเราทำงานได้ตามคุณสมบัติดังกล่าว เราจะต้องสร้างการทำงานสิ่งอื่นๆที่เกี่ยวข้องขึ้นมา ซึ่ง จะมีอยู่  5 ประเภท เรียกรวมๆ ว่า Test Doubles</p>
<h2>Test Doubles คืออะไร</h2>
<p style="text-align: center;"><img fetchpriority="high" decoding="async" class="alignnone size-large wp-image-4565 aligncenter" src="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-1200x530.png" alt="" width="1024" height="452" srcset="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-1200x530.png 1200w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-1024x452.png 1024w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-768x339.png 768w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-600x265.png 600w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-700x309.png 700w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles.png 1296w" sizes="(max-width: 1024px) 100vw, 1024px" />Image from: https://blogs.sap.com/</p>
<p>จริงๆ เราอาจเคยทำมันมาแล้วอย่างใดอย่างหนึ่ง แต่เรามักเรียกกันตามแต่ถนัด เช่น Mock, ระบบจำลอง, ระบบทดสอบ ฯลฯ อะไรก็ว่าไป แต่ที่พบคือ Mock มักถูกใช้บ่อยสุด</p>
<p>คำว่า Test Doubles มาจากหนังสือที่ลุง <a href="http://xunitpatterns.com/Test%20Double%20Patterns.html">Gerard Meszaros</a> เขาเขียนมันขึ้นมา โดยแปลงมาจากคำว่า Stunt Double ที่ใช้ในการทำหนัง ซึ่ง Stunt Double คือ สตั๊นแมนหรือนักแสดงที่มีหน้าตา รูปร่าง แต่งตัวคล้ายกับพระเอก แล้วออกไปแสดงแทนพระเอกในบางฉาก</p>
<p>คราวนี้พอมาเป็น Test Doubles โดยอธิบายมุมเดียวกับ Stunt Double มันก็คือ อะไรบางอย่างที่เราทำมันขึ้นมาเพื่อให้มันทำงานแทนของจริง ในขณะที่เราไม่ได้ต้องการทดสอบมัน อย่างเช่น API ของคนอื่น, Class/Function ของคนอื่น, Database  เป็นต้น</p>
<h2>Test Doubles 5 ประเภท มีอะไรบ้าง</h2>
<p>อย่างที่บอก ว่าเราเคยเรียกทุกสิ่งที่ถูกจำลองว่า Mock  แต่เมื่อพิจารณาดีๆ มันมีจุดแตกต่างกัน ซึ่งเราจะใช้การเรียกประเภทต่างๆ อ้างอิงตามที่ลุง Gerard Meszaros ได้เขียนอธิบายไว้ และทั่วโลกก็ใช้เรียกตามนี้เช่นกัน ดังนั้นเวลาใช้สื่อสารเราจะได้เข้าใจตรงกัน</p>
<p>ปล. ตัวอย่างที่จะใช้ต่อไปนี้ เขียนด้วย .Net Core 2</p>
<h3>1. Dummy</h3>
<p>&nbsp;</p>
<p><img decoding="async" class="alignnone size-full wp-image-4572 aligncenter" src="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Dummy.png" alt="" width="722" height="271" srcset="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Dummy.png 722w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Dummy-600x225.png 600w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Dummy-700x263.png 700w" sizes="(max-width: 722px) 100vw, 722px" /></p>
<p>แปลตรงตัวคือ หุ่นเชิด, ของหลอกตา, คนโง่ เหมือนกับที่เคยมีข่าวว่ากล้องดัมมี่ คือมีแต่กล่องแปะไว้หลอกตาก็อุ่นใจ เช่นกัน ใน Test Doubles มันคือ อะไรก็ได้ ที่ใส่ไปแล้วระบบเราสามารถทำงานได้ หรือคอมไพล์ผ่าน</p>
<p>ถามว่าโง่ได้ขนาดไหน ก็เช่น สร้าง Class เปล่าๆ หรือ Function ที่คืนค่า null หรือ throw exception ก็ยังได้ โดยไม่ต้องสนใจว่ามันทำงานอย่างไร เราสนแค่ว่า ตัวที่เราจะทดสอบสามารถเรียกมันแล้วผ่านไปได้โดยไม่ติดขัด</p>
<p><strong>ตัวอย่าง Dummy</strong></p>
<p>ผมมีโค้ดสำหรับการ Login โดย Constructor Member() จะเป็นส่ง Username/Password ไปตรวจสอบ ซึ่งถ้าถูกต้อง ก็จะทำงานต่างๆ ได้ เช่น แสดงข้อความ &#8220;Welcome to member area&#8221; ใน method Profile()</p>
<p>View the code on <a href="https://gist.github.com/ifew/e9a674894ac6f3101f2c11ea36d47544">Gist</a>.</p>
<p>ผมสร้าง Interface ขึ้นมาชื่อ IAuthorize และคลาสที่ถูกนำไปใช้งานคือ Authorize โดยภายในนั้นมี CheckAuthorize() ซึ่งจะทำการตรวจสอบว่า Login ถูกต้องหรือไม่</p>
<p>และผมสร้างคลาสอีกตัวชื่อ DummyAuthorize เพื่อที่จะใช้ทดสอบ โดยผมไม่ได้ return อะไรออกไปว่าเป็น true/false มีเพียงส่งค่าว่างเปล่าประเภท Boolean ออกไป</p>
<p>View the code on <a href="https://gist.github.com/ifew/a5c31b52c3488e5c65d97cef13d78e48">Gist</a>.</p>
<p>มาดูในไฟล์ Unit Test ซึ่งผมต้องการตรวจสอบว่าสามารถสร้าง Object ของ Member ได้หรือไม่ แต่ติดว่า มันต้องใส่ Username/Password ใน Constructor ด้วยทุกครั้ง ดังนั้น ผมจึงใช้ DummyAuthorize แทน เพื่อให้มันทำงานทะลุผ่านไปได้</p>
<p>View the code on <a href="https://gist.github.com/ifew/1d96adc587c5d57a0e4b7c28a4fb57ed">Gist</a>.</p>
<p>นี่แหละครับ การทำงานของ Dummy ใส่อะไรไปแล้วใช้แทน Dependency ตัวอื่นๆ ได้ เพื่อทะลุไปทำงานอย่างอื่นต่อตามที่ต้องการ ซึ่งในตัวอย่างนี้ ผมลองเช็ค Type Object  Member ดู</p>
<h3>2. Stub</h3>
<p><img decoding="async" class="alignnone size-full wp-image-4564 aligncenter" src="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Stub.png" alt="" width="777" height="271" srcset="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Stub.png 777w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Stub-600x209.png 600w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Stub-768x268.png 768w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Stub-700x244.png 700w" sizes="(max-width: 777px) 100vw, 777px" /></p>
<p>Stub คือการกำหนดสถานะหรือสิ่งต่างๆให้เป็นไปตามที่เราต้องการ (<strong>State verification</strong>) โดยหน้าตาจะคล้ายกับ Dummy แต่ Stub เราจะต้องกำหนดค่าที่จะใช้ด้วย เพื่อให้ได้ผลลัพธ์ออกมาตามที่เราต้องการ</p>
<p>เช่น Test Case ของสมการ 1 + X จะต้องได้เท่ากับ 2 โดยที่ X คือ Function ภายนอกที่เราไปเรียกใช้ และผลลัพธ์จะต้องออกมาเป็น 2 เสมอ ดังนั้น เราจะต้องกำหนดค่า X ว่าต้องเป็น 1 เท่านั้น (ซึ่งต่างจาก Dummy ที่ไม่สนใจการระบุค่า)</p>
<p>และที่เราชอบเรียกกันว่า Mock ส่วนมากคือการทำ Stub นี่เอง เพราะเราเขียนโค้ดขึ้นมาเพื่อให้ได้ค่าอย่างใดอย่างหนึ่งนำไปใช้งานต่อ และแสดงผลลัพธ์ปลายทางที่เราต้องการ</p>
<p><strong>ตัวอย่าง Stub</strong></p>
<p>ผมอ้างอิงจากโค้ดชุดเก่าของ Dummy แต่เปลี่ยน Unit Test ใหม่ โดยผมต้องการตรวจสอบว่า เมื่อเรียกใช้ Profile() จะต้องแสดงข้อความ &#8220;Welcome to member area&#8221; ขึ้นมา</p>
<p>View the code on <a href="https://gist.github.com/ifew/2a112ce61cb112ffec6f997aca415403">Gist</a>.</p>
<p>และเช่นกัน ผมสร้าง Class ชื่อ <span class="pl-en">StubAuthorize</span> จาก <span class="pl-en">IAuthorize </span>และใน CheckAuthorize() จะระบุเป็น true เสมอ เพื่อให้ Unit Test ผมแสดงข้อความ <span class="pl-pds">&#8220;</span>Welcome to member area<span class="pl-pds">&#8221; ขึ้นเสมอ</span></p>
<p>View the code on <a href="https://gist.github.com/ifew/0825095f960938e5dd3c7b60df80f786">Gist</a>.</p>
<p>อาจจะมีความสงสัยว่า ถ้าเราใส่ Username/Password เข้าไปตอนสร้าง object Member เลยได้ไหม อย่างไรก็คืนค่าเป็น  true เสมอ ตอบเลยว่าได้ แต่มีจุดให้คิดเพิ่ม คื อ</p>
<ol>
<li>เราต้องการตรสวจสอบการเรียกใช้ Profile() ว่าแสดงผลถูกต้องหรือไม่ ในสถานะที่เราต้องการให้มันทำงานถูกต้อง ดังนั้นเราไม่ได้ต้องการตรวจสอบ CheckAuthorize() ว่าทำงานถูกต้องหรือไม่ อันนี้จะเขียนเป็นอีก Unit Test หนึ่ง (แต่ก็ไม่ผิดนะครับ เพราะเป็นรูปแบบ Unit Test &#8211; Sociable ซึ่งลองอ่านได้ที่ <a href="https://myifew.com/4480/unit-test-solitary-or-sociable/">รูปแบบการทดสอบของ Unit Test</a>)</li>
<li>แน่ใจหรือไม่ว่า Username/Password ที่ใส่ค้างไว้ จะไม่เปลี่ยนในภายหลัง</li>
</ol>
<h2>3. Mock</h2>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-4562 aligncenter" src="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Mock.png" alt="" width="716" height="131" srcset="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Mock.png 716w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Mock-600x110.png 600w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Mock-700x128.png 700w" sizes="auto, (max-width: 716px) 100vw, 716px" /></p>
<p>ชื่อนี้สร้างความสับสนกันทั้งโลก ซึ่ง Mock ใน Test Doubles จะหมายถึง การทดสอบพฤติกรรมการทำงานของสิ่งๆหนึ่ง (Behavior Verification) อย่าง Class/Function เป็นต้น ว่าทำงานตามที่เราต้องการหรือไม่</p>
<p>กล่าวคือ Mock ไม่ได้สนใจผลลัพธ์ปลายทาง แต่สนใจการทำงานของสิ่งที่ต้องการทดสอบ เช่น ส่งค่าเข้าไปใน process แล้วค่านั้นมีการเปลี่ยนแปลงไปตามที่เราคาดหวังหรือไม่</p>
<p><strong>ตัวอย่าง Mock</strong></p>
<p>ระบบ Login ที่ผมสร้างไว้ จะระบุ Username/Password ผ่าน Constructure ชื่อ Member() จากนั้นจะทำการส่งต่อไปให้ CheckAuthorize() เพื่อตรวจสอบว่าถูกต้องหรือไม่ โดยถ้า ถูกต้อง มันจะแสดงผลออกมาที่ Profile() ว่า &#8220;Welcome to member area&#8221;</p>
<p>ดังนั้น Unit Test ผมจะมีหน้าตาประมาณนี้ ซึ่งผมจะ Assert ไปสองค่าว่า มีการใช้งาน <span class="pl-en">CheckAuthorize</span>() และผลลัพธ์ที่ได้คือ &#8220;Welcome to member area&#8221;</p>
<p>View the code on <a href="https://gist.github.com/ifew/6c47ec08d633ddad7bd8bb9d38da25b4">Gist</a>.</p>
<p>จากนั้นผมสร้าง Class ชื่อ <span class="pl-en">MockAuthorize</span> จาก <span class="pl-en">IAuthorize โดยผมสร้างตัวแปร checkAuthorizeWasCalled ขึ้นมา เพื่อใช้ตรวจสอบการทำงาน</span></p>
<p>View the code on <a href="https://gist.github.com/ifew/e2e7a0a9969612da23efbf92774cc8cc">Gist</a>.</p>
<p>ซึ่งถ้าพฤติกรรมการทำงานของโค้ดผมถูกต้อง จะต้องมีขั้นตอนคือ</p>
<ol>
<li>ส่ง Username/Password ผ่าน Constructure ชื่อ Member()</li>
<li>จากนั้นส่งต่อไปให้ CheckAuthorize()</li>
<li>เปลี่ยนค่าตัวแปร checkAuthorizeWasCalled จากค่า  false เป็น true</li>
<li>โยนกลับมาที่ Profile() ให้แสดงผลลัพธ์</li>
</ol>
<p>เป็นอันว่าพฤติกรรมของ Login ของผมมีการเรียกใช้ CheckAuthorize() เพื่อตรวจสอบ Username/Password ถูกต้องนะ</p>
<p><strong>ตัวอย่าง Mock โดยการใช้ Moq4</strong></p>
<p>คราวนี้เมื่อเราเข้าใจวิธีการปกติแล้ว ลองดูตัวอย่างโค้ดของการใช้ Library ชื่อ Moq4  ซึ่งจะทำให้ง่ายขึ้น เพราะสร้างตัว Mock CheckAuthorize() ไว้ใน Unit Test ได้เลย จากนั้นผม Create Object ขึ้นมา และทำการ Verify ว่ามีการเรียกใช้ CheckAuthorize() เกิดขึ้นหรือไม่</p>
<p>View the code on <a href="https://gist.github.com/ifew/d97756b4bd402230bb8b79f883b41963">Gist</a>.</p>
<h3>4. Spy</h3>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-4563 aligncenter" src="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Spy.png" alt="" width="716" height="221" srcset="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Spy.png 716w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Spy-600x185.png 600w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Spy-700x216.png 700w" sizes="auto, (max-width: 716px) 100vw, 716px" /></p>
<p>ชื่อนี้แปลตรงตัวคือ สายลับ โดยเราจะส่งสายลับไปดูว่า ระบบของเรามีการเรียกใช้ Function ที่เราต้องการทดสอบจริงๆไหม ซึ่งคล้ายกับ Mock แต่แค่ไม่ได้สนใจพฤติกรรมว่าทำอะไรไปบ้าง ต้องได้ค่าอะไร (<strong>Exclusive Behavior Verification</strong>)</p>
<p>เช่น เรามีระบบรายชื่อที่จะต้องส่งอีเมลออกไป 100 รายการ ระบบของเราจะต้องมีการเรียก Function การส่งอีเมลเป็นจำนวน 100 รอบ ตามที่ต้องการจริงๆ</p>
<p><strong>ตัวอย่าง Spy</strong></p>
<p>ผมทำการสร้าง object Member ขึ้นมาสองครั้ง โดยมันจะต้องไปเรียกใช้งาน CheckAuthorize() จำนวนสองครั้งเช่นกัน ดังนั้นผมจึงทดสอบว่ามีการเรียกใช้งานจำนวนสองครั้งจริงหรือไม่</p>
<p>View the code on <a href="https://gist.github.com/ifew/cd60ca3e959184353e3868a8ddd9c3ab">Gist</a>.</p>
<p>จากนั้นผมสร้าง Class ชื่อ <span class="pl-en">SpyAuthorize</span> จาก <span class="pl-en">IAuthorize โดยผมสร้างตัวแปร checkAuthorizeWasCalled ขึ้นมา เพื่อใช้นับจำนวนการเรียกใช้งาน</span></p>
<p>View the code on <a href="https://gist.github.com/ifew/fde5216072837155fe34ae4042eecc0c">Gist</a>.</p>
<p>สังเกตไหมครับว่า Spy มีการเพิ่มโค้ดเพื่อส่งเข้าไปสอดแนมโดยไม่จำเป็นกับการทำงานด้วย ดังนั้นถ้าเราต้องการทดสอบกับโค้ดที่จะใช้งานจริง เช่น คลาส Authorize() มันก็จะต้องเพิ่มเข้าไปในนั้นด้วย มันจึงเป็นข้อเสียอย่างหนึ่ง</p>
<h2>5. Fake</h2>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-4561 aligncenter" src="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Fake.png" alt="" width="701" height="261" srcset="https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Fake.png 701w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Fake-600x223.png 600w, https://myifew.com/wp-content/uploads/2018/07/TestDoubles-Fake-700x261.png 700w" sizes="auto, (max-width: 701px) 100vw, 701px" /></p>
<p>ชื่อก็บอกอยู่ว่าคือการโกหกหลอกลวงนะฮะ ฮ่าๆ มันคือการจำลองอะไรบางอย่างให้เสมือนจริง เหมือนมากจนเป็นข้อเสียหนึ่งที่เราอาจจะสับสนเอง โดยเหมาะกับใช้ในกรณีที่ไม่สามารถทำบน Production หรือระบบที่เราไม่ต้องการให้เกิดผลกระทบ</p>
<p>โดยกรณีนี้ถูกยกตัวอย่างขึ้นมาชัดเจน ก็คือ การใช้ In-Memory เก็บข้อมูลสำหรับทดสอบ แทนการใช้ Database จริงๆ  เป็นต้น</p>
<p>เช่น ระบบมีการสร้าง Order ไว้ใน Database แต่ไม่อยากสร้างจริงใน Database เพราะจะทำให้เลข Order ID ถูกเพิ่มจำนวนเข้าไป และก็ห้ามลบออกด้วย เพราะ Order ID จะขาดช่วง, ดังนั้นเราจะต้องสร้าง Database จำลองขึ้นมา ซึ่งถ้าให้ทุกเครื่องต้องทดสอบได้ และมีความเร็วมากๆ เราก็ต้องใช้ In-Memory นั่นเอง</p>
<p><strong>ตัวอย่าง Fake</strong></p>
<p>ผมต้องการทดสอบว่า Function ชื่อ Get_Member_Information_By_ID() สามารถส่ง Member ID เข้าไป และคืนค่าจาก Database เป็นไปตามที่ผมกำหนดหรือไม่ ดังนั้น แทนที่ผมจะเรียกใช้ Database จริง ผมจึงสร้าง In-Memory Database ขึ้นมาก้อนหนึ่งชื่อ get_by_id_members และทำการใส่ข้อมูลเข้าไปก่อน จากนั้นส่ง Member ID 1 เข้าไปให้ Get_Member_Information_By_ID และทำการตรวจสอบว่า ได้ชื่อ เบอร์โทร วันเดือนปีเกิด ตามใน Database จริงๆหรือไม่</p>
<p>View the code on <a href="https://gist.github.com/ifew/372ecee0dedd227d00e2b368820bda4f">Gist</a>.</p>
<h2>สรุป</h2>
<p>Test Doubles มี 5 ประเภท ที่จะนำไปเลือกใช้ได้ตามสมควร</p>
<ol>
<li><strong>Dummy</strong>: ใช้อะไรก็ได้เพื่อ By Pass การทำงาน แทนการใช้ Dependency จริง</li>
<li><strong>Stub</strong>: กำหนดค่าบางอย่าง เพื่อให้ได้ผลลัพธ์เป็นค่าที่เราต้องการเสมอ</li>
<li><strong>Mock</strong>: เพื่อ verify ว่า process ที่เรียกใช้ มีการส่งค่าไปหา Dependency ตรงตามที่เราคาดหวังหรือเปล่า</li>
<li><strong>Fake</strong>: จำลองบางอย่างขึ้นมาเพื่อใช้แทนของจริง</li>
<li><strong>Spy</strong>: เพื่อ verify ให้แน่ชัดในการใช้ process เช่น โดนเรียกใช้ไปกี่ครั้ง หรือพารามิเตอร์อะไรถูกส่งไปบ้าง</li>
</ol>
<p>หากต้องการเขียน Unit Test เราเลี่ยงไม่ได้ที่จะต้องเรียนรู้เรื่อง Test Doubles เพื่อตัดการเกี่ยวข้องกับสิ่งต่างๆ ทรี่ไม่จำเป็นออก (Dependency) เพราะว่า เราต้องการเจาะจงทดสอบเพียงอย่างเดียวเท่านั้น อย่างอื่นที่ไม่ทดสอบ เราก็จำลองขึ้นมาโดยใช้ Dummy, Stub, Fake ตามแต่จะเลือกใช้ และเราก็ใช้ Mock, Spy เพื่อทดสอบว่าโค้ดที่เขียน มันได้ทำงานถูกต้องจริงๆใช่ไหม ซึ่งวิธีการนี้ นำไปใช้ได้กับทุกภาษาโปรแกรม</p>
<p>และถ้าสังเกตให้ดี จะใช้ Test Double ได้ จำเป็นต้องรู้เรื่อง Unit Test,  Dependency-Injection และการเขียนโปรแกรมแบบ  Object-Oriented ด้วยนะฮะ ไม่เช่นนั้น เข้าใจยากเลยทีเดียว</p>
<h3>อ้างอิง</h3>
<ul>
<li><a href="https://www.javacodegeeks.com/2015/11/test-doubles-mocks-dummies-and-stubs.html" target="_blank" rel="noopener">Test Doubles: mocks, dummies and stubs </a> &lt;&lt; ตัวอย่างน่าสนใจ เข้าใจง่ายดี</li>
<li><a href="https://blog.pragmatists.com/test-doubles-fakes-mocks-and-stubs-1a7491dfa3da" target="_blank" rel="noopener">Test Doubles — Fakes, Mocks and Stubs.</a> &lt;&lt; แนะนำให้อ่านครับ สรุปเข้าใจง่าย ตัวอย่างดี อ่านง่าย</li>
<li><a href="https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html" target="_blank" rel="noopener">The Little Mocker</a> &lt;&lt; แนะนำให้อ่านครับ  อ่านง่าย ตัวอย่างเข้าใจง่ายมาก บทความนี้เขียนจากพื้นฐานเว็บนี้</li>
<li><a href="https://martinfowler.com/articles/mocksArentStubs.html" target="_blank" rel="noopener">Mocks Aren&#8217;t Stubs</a> &lt;&lt; แนะนำให้อ่านครับ อธิบายละเอียดเลย</li>
<li><a href="https://adamcod.es/2014/05/15/test-doubles-mock-vs-stub.html" target="_blank" rel="noopener">Understanding Test Doubles (Mock vs Stub)</a> &lt;&lt; แนะนำให้อ่านครับ สรุปสั้นๆ ตัวอย่างดี อ่านง่าย</li>
<li><a href="http://www.somkiat.cc/test-double-mock-stub-and-dummy/" target="_blank" rel="noopener">มาดูกันว่า Mock, Stub และ Dummy แตกต่างกันอย่างไร ?</a> &lt;&lt; ผมอ้างอิงการแปลภาษาไทยจากเว็บพี่ปุ๋ย</li>
<li>และสุดท้าย กราบขอบพระคุณ<a href="https://www.facebook.com/boyone" target="_blank" rel="noopener">พี่บอย</a> Elder แห่งสยามชำนาญกิจ ที่ช่วยอ่านรีวิวและแนะนำมา ณ ที่นี้ครัช</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://myifew.com/4556/how-to-skip-dependency-in-unit-test-by-test-doubles/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
