Autofixture: ๋™์‹œ ์‚ฌ์ „

์— ๋งŒ๋“  2020๋…„ 04์›” 24์ผ  ยท  6์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: AutoFixture/AutoFixture

์•ˆ๋…•,
autofixture๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Dictionary<T, U> ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ’์ด ์ฑ„์›Œ์ง€์ง€๋งŒ ConcurrentDictionary<T, U> ์—์„œ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์˜๋„์ ์œผ๋กœ ์„ค๊ณ„๋œ ๊ฒƒ์ด๋ฉฐ ์ƒ˜ํ”Œ ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๋™์ž‘์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ๋ˆ„๋ฝ๋œ ๊ธฐ๋Šฅ์ด๋‚˜ ๋ฒ„๊ทธ์ž…๋‹ˆ๊นŒ?

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

์•ˆ๋…•ํ•˜์„ธ์š”,
๊ทธ ์ด์œ ๋ฅผ ๋งํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ง€์›๋˜๋Š” ์ปฌ๋ ‰์…˜์ด ํ•˜๋“œ ์ฝ”๋”ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ "์œ ํ˜•์ด IDictionary๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๊นŒ?"์™€ ๊ฐ™์€ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ "์œ ํ˜• ์‚ฌ์ „<,>์ž…๋‹ˆ๋‹ค."์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ConcurrentDictionary๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ž์‹ ์˜ ๊ฒฌ๋ณธ ์ œ์ž‘๊ธฐ๋ฅผ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์žˆ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

      var fixture = new Fixture();

      var query = new ModestConstructorQuery();
      var methodInvoker = new MethodInvoker(query);
      var dictionaryFiller = new DictionaryFiller();
      var postProcessor = new Postprocessor(methodInvoker, dictionaryFiller);
      var exactTypeSpecification = new ExactTypeSpecification(typeof(ConcurrentDictionary<,>));
      var specimenBuilder = new FilteringSpecimenBuilder(postProcessor, exactTypeSpecification);

      fixture.Customizations.Add(specimenBuilder);

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

๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๊ฐ™์€ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜๋ฉด ์ด์— ๋Œ€ํ•œ ๊ฒฌ๋ณธ ์ž‘์„ฑ๊ธฐ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

public class ConcurrentDictionaryGenerator : ISpecimenBuilder
{
    public object Create(object request, ISpecimenContext context)
    {
        Type type = request as Type;
        if (type == null)
        {
            return new NoSpecimen();
        }

        Type[] typeArguments = type.GetTypeInfo().GetGenericArguments();
        if (typeArguments.Length != 2 || typeof(ConcurrentDictionary<,>).MakeGenericType(typeArguments) != type)
        {
            return new NoSpecimen();
        }

        Type nonConcurrentDictionaryType = typeof(Dictionary<,>).MakeGenericType(typeArguments);
        IDictionary nonConcurrentDictionary = (IDictionary) context.Resolve(nonConcurrentDictionaryType);

        IDictionary concurrentDictionary = (IDictionary) Activator.CreateInstance(type);

        foreach (object key in nonConcurrentDictionary.Keys)
        {
            object value = nonConcurrentDictionary[key];
            concurrentDictionary.Add(key, value);
        }

        return concurrentDictionary;
    }
}

์•ˆ๋…•ํ•˜์„ธ์š”,
๊ทธ ์ด์œ ๋ฅผ ๋งํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ง€์›๋˜๋Š” ์ปฌ๋ ‰์…˜์ด ํ•˜๋“œ ์ฝ”๋”ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ "์œ ํ˜•์ด IDictionary๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๊นŒ?"์™€ ๊ฐ™์€ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ "์œ ํ˜• ์‚ฌ์ „<,>์ž…๋‹ˆ๋‹ค."์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ConcurrentDictionary๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ž์‹ ์˜ ๊ฒฌ๋ณธ ์ œ์ž‘๊ธฐ๋ฅผ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์žˆ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

      var fixture = new Fixture();

      var query = new ModestConstructorQuery();
      var methodInvoker = new MethodInvoker(query);
      var dictionaryFiller = new DictionaryFiller();
      var postProcessor = new Postprocessor(methodInvoker, dictionaryFiller);
      var exactTypeSpecification = new ExactTypeSpecification(typeof(ConcurrentDictionary<,>));
      var specimenBuilder = new FilteringSpecimenBuilder(postProcessor, exactTypeSpecification);

      fixture.Customizations.Add(specimenBuilder);

์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋‚ด๋ถ€์— ๋Œ€ํ•ด ๋” ๋งŽ์ด ์•Œ์ˆ˜๋ก ๋” ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ Dictionary<,> ์—๋งŒ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์ด ํฅ๋ฏธ๋กญ๊ณ  ๋‚ด์žฅ๋œ ๋ฐฉ๋ฒ•์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ๋‚จ์€ ์œ ์ผํ•œ ์งˆ๋ฌธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ถ”๊ฐ€ํ•˜๊ธฐ์— ์ข‹์€ ๊ธฐ๋Šฅ์ด ๋ ๊นŒ์š”? ๊ตฌ์ฒด์ ์œผ๋กœ ConcurrentDictionary<,> ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ชจ๋“  IDictionary<,> ๊ตฌํ˜„์— ์ ์šฉ๋ฉ๋‹ˆ๊นŒ?

์ œ๊ฐ€ ์ž˜๋ชป๋œ ์ •๋ณด๋ฅผ ํผ๋œจ๋ฆฌ์ง€ ์•Š๋Š” ๊ฒƒ์€, Dictionary<,> ๋ฟ๋งŒ์ด ์•„๋‹™๋‹ˆ๋‹ค. Fixture.cs์—์„œ ์ง์ ‘ ์œ ํ˜• ๋ชฉ๋ก์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ง€์ ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด SortedDictionary<,>์ด๊ธฐ๋„ ํ•˜์ง€๋งŒ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ConcurrentDictionary<,>๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.
๋ฐ˜๋“œ์‹œ ๋ฏธ๋ž˜์˜ ๊ตฌํ˜„์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ฒƒ์€ ์ง€์›์ด ์•„๋‹ˆ๋ผ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํŠน์ • ์œ ํ˜•์œผ๋กœ ์ค‘๊ณ„๋œ๋‹ค๋Š” ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค. IDictionary ๋ฐ IReadOnlyDictionary์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Dictionary์— ๋ฆด๋ ˆ์ด๋˜๋Š” ์‹์ž…๋‹ˆ๋‹ค.

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