Autofixture: 'async'๋กœ ํ‘œ์‹œ๋œ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•˜๋Š” ๋Œ€์ฒด GuardClauseAssertion์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2019๋…„ 03์›” 01์ผ  ยท  12์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: AutoFixture/AutoFixture

#268์—์„œ ๋…ผ์˜๋œ ๋ฐ”์™€ ๊ฐ™์ด GuardClauseAssertion ํด๋ž˜์Šค๋Š” ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š์œผ๋ฏ€๋กœ non- fail fast ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฒ€์ฆํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋น ๋ฅธ ํŽ˜์ผ(fail fast) ์ด ์‹ค์ œ๋กœ ์ตœ์„ ์˜ ์„ ํƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์ดํ•ดํ•  async ํ‚ค์›Œ๋“œ๋กœ ํ‘œ์‹œ๋œ ๋ฉ”์†Œ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋น ๋ฅธ ์‹คํŒจ ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

enhancement

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@ploeh ๊ธฐ๋ณธ์ ์œผ๋กœ _any_ async ๋ฉ”์„œ๋“œ๋Š” ์‹คํŒจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ๋ฅผ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

```c#
๊ณต๊ฐœ ๋น„๋™๊ธฐ ์ž‘์—…GuardedOpenGenericMethodReturningTaskResult(๊ฐ์ฒด ์ธ์ˆ˜)
{
if (arg == null) throw new ArgumentNullException(nameof(arg));

await Task.Yield();

return default;

}
```

์ด ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœํ•˜๋ฉด ๋˜์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. null ๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  ์‹คํŒจํ•œ Task ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ˜„์žฌ ํ˜•์‹์˜ GuardClauseAssertion์€ ์‹คํŒจํ•˜๊ณ  ๊ฐ€๋“œ ์ ˆ ๋ˆ„๋ฝ์— ๋Œ€ํ•ด ๋ถˆํ‰ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฑฐ์˜ ๋ชจ๋“  ์ฝ”๋“œ๋Š” async ์ด๋ฏ€๋กœ ๊ฐ ํ˜ธ์ถœ์€ awaited ์ด๊ณ  ์˜ˆ์™ธ๋Š” ์ฆ‰์‹œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์˜ˆ์™ธ๋ฅผ ๋ณด๋ ค๋ฉด await Task๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ํ˜•์‹์—์„œ "๋น ๋ฅธ ์‹คํŒจ" ์›์น™์„ ์œ„๋ฐ˜ํ•˜๋Š” ๊ฒƒ์€ ์™„์ „ํžˆ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ•˜์—ฌ ์ฆ‰์‹œ ์‹คํŒจํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ( async ํ‚ค์›Œ๋“œ๋กœ private ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ  ๋ชจ๋“  ๋…ผ๋ฆฌ๋ฅผ ๊ฑฐ๊ธฐ๋กœ ์ด๋™) ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ์‹ค์šฉ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  12 ๋Œ“๊ธ€

async ํ‚ค์›Œ๋“œ๋กœ ํ‘œ์‹œ๋œ ๋ฉ”์†Œ๋“œ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ _fail fast_ ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

์–ด๋•Œ์š”? ์˜ˆ๋ฅผ ๋“ค์–ด ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@ploeh ๊ธฐ๋ณธ์ ์œผ๋กœ _any_ async ๋ฉ”์„œ๋“œ๋Š” ์‹คํŒจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ๋ฅผ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

```c#
๊ณต๊ฐœ ๋น„๋™๊ธฐ ์ž‘์—…GuardedOpenGenericMethodReturningTaskResult(๊ฐ์ฒด ์ธ์ˆ˜)
{
if (arg == null) throw new ArgumentNullException(nameof(arg));

await Task.Yield();

return default;

}
```

์ด ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœํ•˜๋ฉด ๋˜์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. null ๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  ์‹คํŒจํ•œ Task ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ˜„์žฌ ํ˜•์‹์˜ GuardClauseAssertion์€ ์‹คํŒจํ•˜๊ณ  ๊ฐ€๋“œ ์ ˆ ๋ˆ„๋ฝ์— ๋Œ€ํ•ด ๋ถˆํ‰ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฑฐ์˜ ๋ชจ๋“  ์ฝ”๋“œ๋Š” async ์ด๋ฏ€๋กœ ๊ฐ ํ˜ธ์ถœ์€ awaited ์ด๊ณ  ์˜ˆ์™ธ๋Š” ์ฆ‰์‹œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์˜ˆ์™ธ๋ฅผ ๋ณด๋ ค๋ฉด await Task๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ํ˜•์‹์—์„œ "๋น ๋ฅธ ์‹คํŒจ" ์›์น™์„ ์œ„๋ฐ˜ํ•˜๋Š” ๊ฒƒ์€ ์™„์ „ํžˆ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ•˜์—ฌ ์ฆ‰์‹œ ์‹คํŒจํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ( async ํ‚ค์›Œ๋“œ๋กœ private ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ  ๋ชจ๋“  ๋…ผ๋ฆฌ๋ฅผ ๊ฑฐ๊ธฐ๋กœ ์ด๋™) ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ์‹ค์šฉ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์‹ค์ œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๊ฑฐ์˜ ๋ชจ๋“  ์ฝ”๋“œ๋Š” async ์ด๋ฏ€๋กœ ๊ฐ ํ˜ธ์ถœ์€ awaited ์ด๊ณ  ์˜ˆ์™ธ๋Š” ์ฆ‰์‹œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ์ •๋‹นํ•œ ์ง€์ ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ ์ฃผ์žฅ์„ ๋ฐ›์•„๋“ค์ธ๋‹ค.

๋‚˜๋Š” ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ (๊ฑฐ์˜ ์ฆ๊ฑฐ ์—†์ด) ๋ฌด์–ธ๊ฐ€๊ฐ€ _๋ถˆ๊ฐ€๋Šฅ_ํ•˜๋‹ค๊ณ  ์ฃผ์žฅํ•˜๊ฑฐ๋‚˜ ์•”์‹œํ•  ๋•Œ ๋•Œ๋•Œ๋กœ ๊ธธ์„ ์žƒ์Šต๋‹ˆ๋‹ค...

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋ฌด์–ธ๊ฐ€๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ฃผ์žฅํ•˜๊ฑฐ๋‚˜ ์•”์‹œํ•  ๋•Œ (์ฆ๊ฑฐ๊ฐ€ ๊ฑฐ์˜ ์—†์Œ) ๋•Œ๋•Œ๋กœ ๊ธธ์„ ์žƒ์Šต๋‹ˆ๋‹ค...

์˜ˆ, ์ถฉ๋ถ„ํžˆ ๊ณตํ‰ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜‰

์ด์ œ ๋ถ€์šธ ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋„๋ก GuardClauseAssertion ๋ฅผ ๋‹ค์‹œ ๋””์ž์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‚˜์ค‘์— PR์—์„œ ๋ต™๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด์ œ ๋ถ€์šธ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์—†๋„๋ก GuardClauseAssertion ๋ฅผ ๋‹ค์‹œ ๋””์ž์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

@moodmosaic์ด ์ œ์•ˆํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์ƒˆ ํด๋ž˜์Šค๊ฐ€ ๋” ๋‚˜์€ ๋””์ž์ธ์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด์ง€๋Š” ์•Š์•˜์ง€๋งŒ ํ‹€๋ฆด ์ˆ˜ ์žˆ๋Š” ๊ถŒ๋ฆฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜„

๋‹ค์Œ์€ ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

  1. ๋ฉ”์„œ๋“œ ์„œ๋ช…์˜ async ํ‚ค์›Œ๋“œ ์ œ๊ฑฐ
  2. async ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ค‘์ฒฉ ๋ฉ”์„œ๋“œ ๋งŒ๋“ค๊ธฐ
  3. ๋ฉ”์„œ๋“œ์˜ ๋ฐ”๊นฅ ๋ถ€๋ถ„์— ๊ฐ€๋“œ ์ ˆ์„ ๋„ฃ์Šต๋‹ˆ๋‹ค.
  4. ์ค‘์ฒฉ๋œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

public Task<int> GetNumberAsync(MyObject obj)
{
    // Fail-fast behavior
    if (request is null)
        throw new ArgumentNullException(nameof(obj));

    async Task<int> work()
    {
        var items = await obj.GetItemsAsync(); // whatever you need to call
        return items.Count();
    }

    return work();
}

๊ทธ๊ฒƒ์€ ์ €์—๊ฒŒ ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์˜ ๋„์›€์„ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@mniak @zvirja ๊ฐ€ ์—ฌ๊ธฐ์—์„œ ์ œ์•ˆํ•œ ๊ฒƒ์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ์˜ˆ๊ฐ€ ํฅ๋ฏธ ๋กญ์Šต๋‹ˆ๋‹ค .

๊ฐœ์ธ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ์ด์ ์„ ์œ„ํ•ด "์†์ž„์ˆ˜"๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค์—ผ์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฐฉ์‹์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ๋ฐฉ์‹์œผ๋กœ ์ง€์›์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์—ด์–ด ๋‘์‹ญ์‹œ์˜ค. ์–ด๋Š ๋‚ . ๊ฐ€๊นŒ์šด ๋ฏธ๋ž˜์—. ์•„๋‹ˆ๋ฉด ๋‹จ ํ•˜๋ฃจ.

์•ˆ๋…•ํ•˜์„ธ์š”. ์šฐ๋ฆฌ๋Š” ์ •ํ™•ํžˆ ์ด ๋ฌธ์ œ๋ฅผ ์šฐ์—ฐํžˆ ๋ฐœ๊ฒฌํ–ˆ๊ณ  ํ˜„์žฌ๊นŒ์ง€ ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์ด ์—†๋‹ค๋Š” ์‚ฌ์‹ค์— ๋†€๋ž์Šต๋‹ˆ๋‹ค.
์ด๋ฅผ ์œ„ํ•ด ์ƒˆ ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์„ ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?
AutoFixture์˜ ๋‚ด๋ถ€ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ๋ชจ๋ฅด์ง€๋งŒ Method-to-Test์— ๋Œ€ํ•œ GuardClauseAssertion ํด๋ž˜์Šค ๋‚ด์—์„œ MethodInfo๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ CustomAttributes๋ฅผ ์‚ดํŽด๋ณด๊ณ  ์ด๊ฒƒ์ด ๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(https:/ /stackoverflow.com/a/20350646). ๊ทธ๋ž˜์„œ ์•„๋งˆ๋„ ์Šค์œ„์น˜(bool vs. new class)๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@zvirja @aivascu ์ด๊ฒƒ์„ ์žฌ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? 2021๋…„์— ๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๋Œ€๋กœ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์—†๋Š” ์ด์œ ๋ฅผ ์ •๋ง ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

@Kralizek ์ƒํ™ฉ์„ ์ œ๋Œ€๋กœ ์ฝ์—ˆ๋‹ค๋ฉด ์š”์ฒญ์ด ๊ฑฐ๋ถ€๋˜์ง€ ์•Š์•˜๊ณ , ์‹ฌ์ง€์–ด ๊ทธ๊ฒƒ์„ ์ˆ˜์ •ํ•˜๋Š” PR๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‚˜๋Š” PR์„ ๊ฐ„๋žตํ•˜๊ฒŒ ์‚ดํŽด๋ณด์•˜๊ณ  ๋ฐ›์€ ํ”ผ๋“œ๋ฐฑ์— ๋™์˜ํ•œ๋‹ค๊ณ  ๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ๋‚จ์€ ๊ฒƒ์€ ํ”ผ๋“œ๋ฐฑ์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ๊ตฌํ˜„๋œ ํ”ผ๋“œ๋ฐฑ๊ณผ ํ•จ๊ป˜ ์ƒˆ PR์„ ์ œ์ถœํ•˜๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค.

๋ชจ๋ฐ”์ผ ์•ฑ์—์„œ ๋งํฌ๋œ PR์ด ์•ˆ๋ณด์—ฌ์š” ๐Ÿ˜‚

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰