๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“‚ ์•Œ์“ธ ์ง€์‹/์•Œ์•„๋‘๋ฉด ์ข‹์„

ํ…Œ์ŠคํŠธ ๋”๋ธ” Mock vs. Stub vs. Spy ์ฐจ์ด ์•Œ์•„๋ณด๊ธฐ

by Dev. Ella 2023. 11. 27.

๐Ÿ““ ํ…Œ์ŠคํŠธ ๋”๋ธ”

์ผ๋‹จ ์š”์•ฝํ•˜์ž๋ฉด Mock, Stub, Spy ๊ฐ๊ฐ์€ ํ…Œ์ŠคํŠธ์˜ ๋ชฉ์ ๊ณผ ์š”๊ตฌ ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ , ์ข…์ข… ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๊ธฐ๋„ ํ•œ๋‹ค. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋‹ค ๋ณด๋ฉด ์œ„ ์„ธ ๊ฐ€์ง€ ๊ฐœ๋…์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์งš๊ณ  ๋„˜์–ด๊ฐ€ ๋ณด์ž.

 

Mock, Stub, Spy๋Š” ์†Œํ”„ํŠธ์›จ์–ด ํ…Œ์ŠคํŠธ์—์„œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ์šฉ์–ด๋กœ, ๋ชจ๋‘ ํ…Œ์ŠคํŠธ ๋”๋ธ”(test double)์˜ ์ผ์ข…์ด๋‹ค.

 

ํ…Œ์ŠคํŠธ ๋”๋ธ”์ด๋ž€, xUnit Test Patterns์˜ ์ €์ž์ธ ์ œ๋ผ๋“œ ๋ฉ”์Šค์ž๋กœ์Šค(Gerard Meszaros)๊ฐ€ ๋งŒ๋“  ์šฉ์–ด๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒฝ์šฐ ์ด๋ฅผ ๋Œ€์‹ ํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฐ์ฒด๋ฅผ ๋งํ•œ๋‹ค. (์ฐธ๊ณ : Test Double์„ ์•Œ์•„๋ณด์ž)

 

ํ…Œ์ŠคํŠธ ๋”๋ธ” (Test Double)

 

๊ฐ๊ฐ์€ ํ…Œ์ŠคํŠธ ์ค‘์— ์™ธ๋ถ€ ์‹œ์Šคํ…œ์ด๋‚˜ ๋ณต์žกํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๋ฐ์— ์‚ฌ์šฉ๋˜์ง€๋งŒ, ๊ทธ ๋ชฉ์ ๊ณผ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅด๋‹ค. ์•„๋ž˜์— ์ด๋“ค์˜ ์ฐจ์ด์ ์„ ์ •๋ฆฌํ•ด ๋ณด์•˜๋‹ค.

 

 

โœ… Mock

๊ธฐ๋Œ€ํ•œ ๋Œ€๋กœ ์ž˜ ํ˜ธ์ถœ๋˜๋‚˜?

 

Mock์€ ๋ฐ˜ํ™˜๊ฐ’์ด ์—†๋Š” ํ•จ์ˆ˜๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ, ํŠน์ • ๊ฐ์ฒด์—์„œ ํŠน์ • ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ๋‹ค์‹œ ๋งํ•˜๋ฉด, ๋‚ด๊ฐ€ ๋ฐ”๋ผ๋Š” ํ˜ธ์ถœ์— ๋Œ€ํ•œ ๊ธฐ๋Œ€๋ฅผ ๋ช…์‹œํ•ด ๋‘๊ณ , ๋ช…์‹œํ•œ ๋‚ด์šฉ์— ๋”ฐ๋ผ ์ž˜ ์ž‘๋™ํ•˜๋Š”์ง€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๋œ ๊ฐ์ฒด์ธ ๊ฑฐ๋‹ค.

 

Mock์€ ํ…Œ์ŠคํŠธ ์ค‘์— ํŠน์ • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์ฆ‰, ๊ฐ€์งœ ํ…Œ์ŠคํŠธ ์ˆ˜๋‹จ์„ ๋งŒ๋“ค์–ด ๋‘๋Š” ๊ฑฐ๋‹ค. ์ด๋ ‡๊ฒŒ ๋Œ€์ฒด๋œ Mock ๊ฐ์ฒด๋Š” ์œ„์— ์–ธ๊ธ‰ํ•œ ๋Œ€๋กœ ํŠน์ • ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€, ์–ด๋–ค ์ธ์ž๋กœ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘”๋‹ค.

 

Mock์€ ํ…Œ์ŠคํŠธ ๋Œ€์ƒ์˜ ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ๋Œ€์ฒดํ•˜๊ณ , ๊ทธ ๊ฐ์ฒด์˜ ํ–‰๋™์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋กœ๋ถ€ํ„ฐ ์กฐํšŒํ•œ ๊ฐ’์„ ์—ฐ์‚ฐํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ์ƒํ™ฉ์ด๋ผ๊ณ  ํ•˜์ž. ์ด ๋กœ์ง์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด์ฉ” ์ˆ˜ ์—†์ด DB์˜ ์˜ํ–ฅ์„ ๋ฐ›์„ ๊ฒƒ์ด๋ฏ€๋กœ DB ์ƒํƒœ์— ๋”ฐ๋ผ ๋งค๋ฒˆ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ๊ธฐ์— ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ธฐ์—๋Š” ๋ถˆ์•ˆ์ •ํ•œ ์ƒํ™ฉ์ด๋‹ค. ๋ถˆ์•ˆ์ •ํ•˜๊ธฐ์— ์•ˆ์ •์ ์ธ ๋Œ€์ƒ์œผ๋กœ ๋Œ€์ฒดํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์šฐ์•„ํ•œ ํ…Œํฌ์ฝ”์Šค ํ”„๋ฆฌ์ฝ”์Šค ์ค‘, ์ˆซ์ž ์•ผ๊ตฌ ๋ฏธ์…˜์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ผ๋ถ€๋ฅผ ๋ณด๋ฉฐ mock์„ ์ดํ•ดํ•ด ๋ณด์ž.

 

test('๊ฒŒ์ž„ ์ข…๋ฃŒ ํ›„ ์žฌ์‹œ์ž‘', async () => { 
 // ... ์ƒ๋žต

 mockRandoms(randoms);
 mockQuestions(answers);

 // App ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ๋ฐ play ํ•จ์ˆ˜ ์‹คํ–‰
 const app = new App();
 await expect(app.play()).resolves.not.toThrow();

 // ๋กœ๊ทธ ์ถœ๋ ฅ์ด ์˜ˆ์ƒ๋Œ€๋กœ ์ด๋ฃจ์–ด์กŒ๋Š”์ง€ ๊ฒ€์ฆ
 messages.forEach((output) => { 
  expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output));
 });
});

 

์œ„ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด Mock ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์ถ”์ ํ•˜๊ณ , ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ํŠน์ • ์กฐ๊ฑด์— ๋งž๊ฒŒ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์ฆํ•œ๋‹ค. ๋•๋ถ„์— ํŠน์ • ์ƒํ™ฉ์—์„œ ์ ์ ˆํ•œ ๋กœ๊ทธ๊ฐ€ ์ถœ๋ ฅ๋˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

โœ… Stub

๊ธฐ๋Œ€ํ•œ ๊ฐ’์ด ์ž˜ ๋ฐ˜ํ™˜๋˜๋‚˜?

 

Stub์€ ํŠน์ • ๊ฐ์ฒด์—์„œ ํŠน์ • ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, ํŠน์ •ํ•œ ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜๋ฉฐ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. 'stub'์˜ ์‚ฌ์ „์  ์˜๋ฏธ๋ฅผ ๋ฏธ๋ฃจ์–ด ๋ณด์•„, ์–ด๋–ค ์ฐŒ๊บผ๊ธฐ ๊ฐ™์€ ๊ฒƒ์„ ์ค€๋น„ํ•ด ๋‘์–ด, ๊ธฐ๋Œ€ํ•œ ๊ฐ’์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

 

stub์˜ ์‚ฌ์ „์  ์˜๋ฏธ @naverdic

 

๊ตฌ์ฒด์ ์œผ๋กœ ํ’€์–ด ๋งํ•˜์ž๋ฉด, stub์€ dummy ๊ฐ์ฒด๊ฐ€ ์‹ค์ œ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๊พธ๋ฉฐ ๋†“์€ ๊ฐ์ฒด๋กœ, ํ…Œ์ŠคํŠธ์—์„œ ํ˜ธ์ถœ๋œ ์š”์ฒญ์— ๋Œ€ํ•ด ๋ฏธ๋ฆฌ ์ค€๋น„ํ•ด ๋‘” ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋‚ด๊ฐ€ ๊ธฐ๋Œ€ํ•œ ๊ฐ’์ด ์ž˜ ๋ฐ˜ํ™˜๋˜๋Š”์ง€ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Stub์€ ํ…Œ์ŠคํŠธ ์ค‘์— ์‚ฌ์šฉ๋˜๋Š” ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ฐ’ ๋˜๋Š” ์‘๋‹ต์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ๋ณต์žกํ•œ ๋กœ์ง์ด๋‚˜ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๋‹จ์ˆœํ™”ํ•˜๊ณ , ํ…Œ์ŠคํŠธ๋ฅผ ๋” ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐ ์ค‘์ ์„ ๋‘๋ฉฐ, ์ธํ„ฐํŽ˜์ด์Šค ๋˜๋Š” ๊ธฐ๋ณธ ํด๋ž˜์Šค๊ฐ€ ์ตœ์†Œํ•œ์œผ๋กœ ๊ตฌํ˜„๋œ ์ƒํƒœ๋‹ค.

 

์šฐ์•„ํ•œ ํ…Œํฌ์ฝ”์Šค ํ”„๋ฆฌ์ฝ”์Šค ์ค‘, ์ž๋™์ฐจ ๊ฒฝ์ฃผ ๋ฏธ์…˜์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ผ๋ถ€๋ฅผ ๋ณด๋ฉฐ stub์„ ์ดํ•ดํ•ด ๋ณด์ž.

 

test.each([
  [['pobi,javaji']],
  [['pobi,eastjun']]
])('์ด๋ฆ„์— ๋Œ€ํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ', async (inputs) => {
  // given: ์งˆ๋ฌธ ๋ชจ์˜๋ฅผ ์„ค์ •
  mockQuestions(inputs);
  
  // when: App ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑ
  const app = new App();

  // then: App์˜ play ๋ฉ”์†Œ๋“œ๊ฐ€ ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰๋  ๋•Œ ์˜ˆ์™ธ '[ERROR]'๋ฅผ ๋˜์ง€๋Š”์ง€ ํ™•์ธ
  await expect(app.play()).rejects.toThrow('[ERROR]');
});

 

์œ„ ์ฝ”๋“œ์—์„œ [['pobi,javaji']], [['pobi,eastjun']]๋Š” ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” stub์œผ๋กœ์„œ, ์‹ค์ œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ๋Œ€์‹ ํ•ด ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ App ํด๋ž˜์Šค์˜ ๋™์ž‘์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

์ฐธ๊ณ ๋กœ test.each ๋ฉ”์„œ๋“œ๋Š” ์ด๋Ÿฌํ•œ ์Šคํ…๋“ค์„ ๋‹ค๋ฃจ๋Š” ๋ฐ์— ๋นˆ๋ฒˆํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”๋ฐ, ๊ฐ๊ฐ์˜ ๋ฐฐ์—ด์ด ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์ž…๋ ฅ ์‹œ๋‚˜๋ฆฌ์˜ค์— ๋Œ€ํ•œ ๋™์ž‘์— ๋Œ€ํ•œ ์ฝ”๋“œ์˜ ๋ฐ˜๋ณต์„ ์ค„์ด๋ฉด์„œ ํšจ์œจ์ ์œผ๋กœ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

โœ… Spy

ํ•จ์ˆ˜๊ฐ€ ์ž˜ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‚˜?

 

Spy๋Š” ํŠน์ • ํ•จ์ˆ˜๋งŒ ์‹ค์ œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ, ๊ธฐ์กด์˜ ๊ฐ์ฒด๋‚˜ ํ•จ์ˆ˜๋ฅผ ๊ฐ์‹œํ•˜๋Š” ๋ฐ์— ์‚ฌ์šฉ๋œ๋‹ค. ์ด๋•Œ ํ•จ์ˆ˜ ํ˜ธ์ถœ, ์ „๋‹ฌ๋œ ์ธ์ž, ๋ฐ˜ํ™˜๊ฐ’ ๋“ฑ์„ ๊ธฐ๋กํ•˜์ง€๋งŒ, ์‹ค์ œ ๋กœ์ง์˜ ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.

 

ํ’€์–ด ์„ค๋ช…ํ•˜์ž๋ฉด, Spy๋Š” ์ฃผ๋กœ ํ…Œ์ŠคํŠธ ์ค‘์— ํŠน์ • ํ•จ์ˆ˜๋‚˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€ ๊ด€์ฐฐํ•˜๊ณ  ๊ธฐ๋กํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ๋งˆ์น˜ ๊ฒ€์€์ƒ‰ ์˜ท์„ ์ž…์€ ์ŠคํŒŒ์ด๊ฐ€ ํŠน์ • ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ์„ ๋•Œ ํ™•์ธ์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ๊ธฐ๋กํ•˜๊ณ  ์žˆ๋Š” ๋ชจ์Šต์„ ์ƒ์ƒํ•˜๋ฉด ๋œ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด, ํ•จ์ˆ˜๊ฐ€ ๋ช‡ ๋ฒˆ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€, ์–ด๋–ค ์ธ์ž๋กœ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€ ๋“ฑ์„ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์‹ค์ œ ๊ตฌํ˜„์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ํ•จ์ˆ˜์˜ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ํŠน์ง•์ด๋‹ค.

 

์šฐ์•„ํ•œ ํ…Œํฌ์ฝ”์Šค ํ”„๋ฆฌ์ฝ”์Šค ์ˆซ์ž ์•ผ๊ตฌ ๋ฐ ์ž๋™์ฐจ ๊ฒฝ์ฃผ ๋ฏธ์…˜์— ๊ณตํ†ต์œผ๋กœ ๋“ฑ์žฅํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ผ๋ถ€๋ฅผ ๋ณด๋ฉฐ spy๋ฅผ ์ดํ•ดํ•ด ๋ณด์ž.

 

// ๋กœ๊ทธ ์ถœ๋ ฅ์„ ๊ฐ์‹œํ•˜๋Š” Spy ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑ
const getLogSpy = () => {
  // MissionUtils์˜ Console.print๋ฅผ ๊ฐ์‹œ
  const logSpy = jest.spyOn(MissionUtils.Console, 'print');
  // ์ด์ „์˜ ๊ฐ์‹œ ๊ธฐ๋ก์„ ์ดˆ๊ธฐํ™”
  logSpy.mockClear();
  // ์ƒ์„ฑ๋œ Spy ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
  return logSpy;
};

 

์œ„ ์˜ˆ์‹œ ์ฝ”๋“œ์—์„œ๋Š” jest.spyOn์„ ์‚ฌ์šฉํ•˜์—ฌ MissionUtils.Console.print ํ•จ์ˆ˜์— ๋Œ€ํ•œ spy๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ, ์ด spy๋Š” print ํ•จ์ˆ˜์˜ ์‹ค์ œ ํ˜ธ์ถœ์„ ๊ฐ์‹œํ•˜๊ณ  ๊ธฐ๋กํ•œ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ์„ ๋•Œ์˜ ์ธ์ž, ํ˜ธ์ถœ ํšŸ์ˆ˜ ๋“ฑ์„ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๊ณ , ์•ž์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์‹ค์ œ ํ•จ์ˆ˜์˜ ๋กœ์ง์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋œ๋‹ค.

 

 

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป ์š”์•ฝํ•˜์ž๋ฉด

· Mock์€ ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ๋ชจ์˜ํ•˜๊ณ , ํŠน์ • ํ–‰๋™์ด ๋ฐœ์ƒํ–ˆ๋Š”์ง€๋ฅผ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
· Stub์€ ํ…Œ์ŠคํŠธ ์ค‘์— ํ•„์š”ํ•œ ๋ฏธ๋ฆฌ ์ •ํ•ด์ง„ ์‘๋‹ต์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
· Spy๋Š” ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ๊ฐ์‹œํ•˜๋ฉด์„œ ํ˜ธ์ถœ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•˜์ง€๋งŒ, ๊ฐ์ฒด์˜ ์‹ค์ œ ๋™์ž‘์€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

์•ž์œผ๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” ์œ„์˜ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์ด ์ œ๊ณตํ•ด ์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ ์žฌ์ ์†Œ์— ์‚ฌ์šฉํ•˜๋ฉฐ ์ œ๋Œ€๋กœ ๋œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด์ž. ์–ด๋–ค ์ƒํ™ฉ์— ์–ด๋–ค ๊ฒƒ์„ ์จ์•ผ ํ•˜๋Š”์ง€ ํ•™์Šตํ•˜๊ณ  ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋” ์ข‹์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ.

 

 

๐Ÿ“‹ ์ฐธ๊ณ  ์ž๋ฃŒ

- Mock VS Stub VS Spy

- Tecoble: Test Double์„ ์•Œ์•„๋ณด์ž

 

 

 

๋Œ“๊ธ€