์๋
ํ์ธ์, ์ ๋ ICustomization
์ฌ์ฉํ์ฌ ISpecimenBuilder.CreateMany
ICustomization
๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณ ์ ํ ๊ฐ์ ์์ฑํ ์ ์๊ธฐ๋ฅผ ์ํฉ๋๋ค. AutoFixture๊ฐ ๋ชจ๋ ์ํฐํฐ์ ๋ํด ๋์ผํ ๊ฐ์ ์์ฑํ๋ฏ๋ก ์ต์์ ์๋ฃจ์
์ด ๋ฌด์์ธ์ง ๊ถ๊ธํ์ต๋๋ค.
```c#
๊ณต๊ฐ ํด๋์ค FooCustomization : ICustomization
{
public void ์ปค์คํฐ๋ง์ด์ง(IFixture ์กฐ๋ช
๊ธฐ)
{
var ํ๋ณธ = fixture.Build
.OmitAutoProperties()
.With(x => x.CreationDate, DateTime.Now)
.With(x => x.Identifier, Guid.NewGuid().ToString().Substring(0, 6)) // ๊ณ ์ ํ ๊ฐ์ ์์ฑํด์ผ ํจ
.With(x => x.Mail, $"[email protected]")
.์ฐฝ์กฐํ๋ค();
fixture.Register(() => specimen);
}
}
```
์ถ์ .: ์ฃผ์ ๋ชฉํ๋ ๋ด ํ
์คํธ์ ์ฝ๋ ์์ ์ค์ด๋ ๊ฒ์ด๋ฏ๋ก ๋ชจ๋ ํ
์คํธ์ ๊ฐ์ ์ฌ์ฉ์ ์ ์ํ๊ธฐ ์ํด With()
๋ฅผ ํธ์ถํ๋ ๊ฒ์ ํผํด์ผ ํฉ๋๋ค. ์ด ์์
์ ์ํํ๋ ์ ์ ํ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
์
๋ฐ์ดํธ: ๋ฐฉ๊ธ @ploeh ์์ ์ด ์๋ต์ https://github.com/AutoFixture/AutoFixture/issues/361#issuecomment -86873060 ์ด๊ฒ์ด ๋ด๊ฐ ์ฐพ๊ณ ์๋ ๊ฒ์ผ ์ ์์ต๋๋ค.
์ด ์ ๊ทผ ๋ฐฉ์์๋ ๋ง์ ๋จ์ ์ด ์์ต๋๋ค. ๋จผ์ Create<List<Foo>>()
๋ฅผ ํธ์ถํ๋ ๊ฒ์ ๋งค์ฐ ์ง๊ด์ ์ด์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ์๋ํ๋ฉด CreateMany<Foo>
์์ ๊ธฐ๋ํ ์ ์๋ ๋ชฉ์ ์ ๋ค์ ์ด๊ธ๋๊ธฐ ๋๋ฌธ์
๋๋ค. ํ๋ ์ฝ๋ฉ ๋ ํฌ๊ธฐ์ ๋ชฉ๋ก์ ์์ฑํฉ๋๋ค.>(?). ๋ ๋ค๋ฅธ ๋จ์ ์ ๊ฐ ์ํฐํฐ์ ๋ํด ๋ ๊ฐ์ง ์ฌ์ฉ์ ์ง์ ์ด ํ์ํ๋ค๋ ๊ฒ์
๋๋ค. ํ๋๋ ์ฌ์ฉ์ ์ง์ ์ปฌ๋ ์
์ ๋ง๋ค๊ณ ๋ค๋ฅธ ํ๋๋ ๋จ์ผ ์ธ์คํด์ค๋ฅผ ๋ง๋๋ ๋ฐ ์ฌ์ฉํฉ๋๋ค. ์ปฌ๋ ์
์ ๋ง๋ค๊ธฐ ์ํด
Create<T>
์ ๋์์ ์ฌ์ ์ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
์ด๊ฒ์ ์คํ ์ค๋ฒํ๋ก ์ง๋ฌธ์ ๋ํ ์ข์ ํ๋ณด์ฒ๋ผ ๋ณด์ ๋๋ค. ์ฌ๊ธฐ์ ์ง๋ฌธํ๋ ๊ฒ์ด ์๋ชป๋ ๊ฒ์ ์๋์ง๋ง ์ด ์ง๋ฌธ์ ๋ต๋ณ์ด ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ๋ ๋์์ด ๋ ์ ์๋ ์ข ๋ฅ์ด๊ณ GitHub ๋ฌธ์ ์ ๋นํด Stack Overflow์์ ์ง๋ฌธ๊ณผ ๋ต๋ณ์ ์ฐพ๋ ๊ฒ์ด ๋ ์ฝ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์๋ฅผ ๋ค์ด, Google์ ์คํ ์ค๋ฒํ๋ก ์ง๋ฌธ์ ๋ํ ์ธ๋ฑ์ฑ์ ์ ์ํํ์ง๋ง GitHub ๋ฌธ์ ์ ์์๋ (๋ซํ) ๋ ๋ฎ์ ๊ฒ ๊ฐ์ต๋๋ค...
@ploeh ๊ณต๊ฐํฉ๋๋ค....
๋ฐฉ๊ธ ์ด ๋ฌธ์ ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก SO ์ง๋ฌธ์ ๋ง๋ค์์ต๋๋ค. ์ถํ ์ฐธ๊ณ ํ ์ ์๋ ๋งํฌ ์
๋๋ค ๐
@ploeh SO :blush์ ๋ํ ์ง๋ฌธ์ ๋ต๋ณํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
@thiagomajesk ์ค์ ๋ก ์ฌ๊ธฐ์ ์ง๋ฌธ์ ๋ตํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. Mark๊ฐ SO๋ฅผ ์ ์ํ ์ด์ ๋ ๊ทธ๊ฒ์ด ์ ๊ณตํ๋ ๊ฒ์ ๊ธฐ๋ฅ ๋๋ฌธ์ ๋๋ค. ๋ํ ํ์ฌ Mark๋ SO๋ฅผ ๋ชจ๋ํฐ๋งํ๊ณ ์์ผ๋ฏ๋ก ๊ฑฐ๊ธฐ์ ์ง๋ฌธ์ ๊ฒ์ํ๋ฉด ๊ทธ์ ์ ๋ฌธ ์ง์์ ์ป์ ์ ์๋ ๋ ๋ง์ ๊ธฐํ๊ฐ ์์ต๋๋ค(์ด๋ฒ์ ์ป์ ๊ฒ์ฒ๋ผ) :sweat_smile:
@zvirja ์ค๋ช ํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค ๐
@zvirja @ploeh ์ ํ๋ฅญํ ๋ต๋ณ์ ๊ธฐ๋ฐ์ผ๋ก SO์ ๋ํ ์ง๋ฌธ์ ๋ง๋ฌด๋ฆฌํ๊ฒ ์ต๋๋ค .
ํ์ง๋ง ์ด์ ๋ํ ๊ตฌํ ์ธ๋ถ ์ ๋ณด์ ๋ํด ์กฐ๊ธ ๋ ์๊ณ ์ถ์ต๋๋ค.
์ฃผ์ ์์ ๋ ์ด์ ๋ฒ์ด๋๊ณ ์ถ์ง ์๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์์ ์ด ์ธ๋ถ ์ฌํญ์ ๋ํด ๋ฌป๋ ๊ฒ์ด ๋ ๋์ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋์ ๋๋์ด ๊ตฌํ์ด ์์ต๋๋ค :
```c#
๊ณต๊ฐ ํด๋์ค UniqueShortGuidBuilder
{
๊ฐ์ธ ์ฝ๊ธฐ ์ ์ฉ ๋ฌธ์์ด propName;
๊ฐ์ธ ์ฝ๊ธฐ ์ ์ฉ int ๊ธธ์ด;
public UniqueShortGuidBuilder(Expression<Func<TEntity, string>> expr, int lenght)
{
propName = ((MemberExpression)expr.Body).Member.Name;
this.lenght = lenght;
}
๊ณต์ฉ ๊ฐ์ฒด ์์ฑ(๊ฐ์ฒด ์์ฒญ, ISpecimenContext ์ปจํ
์คํธ)
{
var pi = PropertyInfo๋ก ์์ฒญ;
if (pi == null || pi.PropertyType != typeof(string) || pi.Name != propName)
return new NoSpecimen();
return Guid.NewGuid().ToString().Substring(0, lenght);
}
```
AutoFixture๋ก ๋ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ISpecimenBuilder.Create
๊ฐ ์ฌ๋ฌ ๋ฒ ํธ์ถ๋์ด ๋ด ์ํฐํฐ์ ๋ํด ๊ณ ์ ํ Guid๊ฐ ์์ฑ๋ ๊ฒ์ผ๋ก ์์ํ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ถ๋ช
ํ ์ด๊ฒ์ ์ฌ์ค์ด ์๋๋ฉฐ ์ค์ ๋ก ๋์ผํ ๊ฒ์ ๊ณต์ ํ๊ณ ์์ต๋๋ค.
๊ธ์์, ๋ฐฉ๊ธ ๊ทํ์ ์ฝ๋๋ฅผ ํ ์คํธํ์ผ๋ฉฐ ์ํ๋ ๋๋ก ์ ํํ๊ฒ ์๋ํ์ต๋๋ค.
```c#
๊ณต๊ฐ ํด๋์ค ํธ
{
๊ณต๊ฐ ๋ฌธ์์ด PropertyToCustomize { ๊ฐ์ ธ์ค๊ธฐ; ์ธํธ; }
}
๊ณต๊ฐ ํด๋์ค UniqueShortGuidBuilder
{
๊ฐ์ธ ์ฝ๊ธฐ ์ ์ฉ ๋ฌธ์์ด propName;
๊ฐ์ธ ์ฝ๊ธฐ ์ ์ฉ int ๊ธธ์ด;
public UniqueShortGuidBuilder(Expression<Func<TEntity, string>> expr, int lenght)
{
propName = ((MemberExpression) expr.Body).Member.Name;
this.lenght = lenght;
}
public object Create(object request, ISpecimenContext context)
{
var pi = request as PropertyInfo;
if (pi == null || pi.PropertyType != typeof(string) || pi.Name != propName)
return new NoSpecimen();
return Guid.NewGuid().ToString().Substring(0, lenght);
}
}
[์ฌ์ค]
๊ณต๊ฐ ๋ฌดํจ TestCustomization()
{
var ๊ณ ์ ์ฅ์น = new Fixture();
Fixture.Customizations.Add(new UniqueShortGuidBuilder
var manyFoos = fixture.CreateMany<Foo>(10);
var uniqueIds = manyFoos
.Select(x => x.PropertyToCustomize)
.Where(x => x.Length == 5)
.Distinct()
.ToArray();
Assert.Equal(10, uniqueIds.Length);
}
```
๋ฐ๋ผ์ ์ค์ ์ฝ๋๊ฐ ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ๋ค์ ํ์ธํ์ฌ ๊ทธ ์ฐจ์ด๊ฐ ์ค์ํ ์ด์ ๋ฅผ ์ดํดํ ์ ์๋๋ก ํ๊ณ ์ถ์ต๋๋ค. ๐
@zvirja ์ด์
Fixture.Customize(new FooCustomization());
ํ๋ฉด ํ
์คํธ๊ฐ ํต๊ณผํ๊ณ ๊ทธ๋ ์ง ์์ผ๋ฉด ํต๊ณผํ์ง ๋ชปํฉ๋๋ค.
```c#
์์คํ
์ฌ์ฉ;
Microsoft.VisualStudio.TestTools.UnitTesting ์ฌ์ฉ;
AutoFixture.Kernel ์ฌ์ฉ;
System.Linq.Expressions ์ฌ์ฉ;
System.Reflection ์ฌ์ฉ;
AutoFixture ์ฌ์ฉ;
System.Linq๋ฅผ ์ฌ์ฉํ์ฌ;
๋ค์์คํ์ด์ค UnitTestProject1
{
๊ณต๊ฐ ํด๋์ค ํธ
{
๊ณต๊ฐ ๋ฌธ์์ด PropertyToCustomize { ๊ฐ์ ธ์ค๊ธฐ; ์ธํธ; }
}
public class FooCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
var specimen = fixture.Build<Foo>()
.OmitAutoProperties()
.With(x => x.PropertyToCustomize)
.Create();
fixture.Register(() => specimen);
}
}
public class UniqueShortGuidBuilder<TEntity> : ISpecimenBuilder
{
private readonly string propName;
private readonly int lenght;
public UniqueShortGuidBuilder(Expression<Func<TEntity, string>> expr, int lenght)
{
propName = ((MemberExpression)expr.Body).Member.Name;
this.lenght = lenght;
}
public object Create(object request, ISpecimenContext context)
{
var pi = request as PropertyInfo;
if (pi == null || pi.PropertyType != typeof(string) || pi.Name != propName)
return new NoSpecimen();
return Guid.NewGuid().ToString().Substring(0, lenght);
}
}
[TestClass]
public class UnitTest1
{
public static Fixture Fixture { get; private set; }
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
Fixture = new Fixture();
Fixture.Customizations.Add(new UniqueShortGuidBuilder<Foo>(x => x.PropertyToCustomize, 5));
Fixture.Customize(new FooCustomization());
}
[TestMethod]
public void TestMethod1()
{
var manyFoos = Fixture.CreateMany<Foo>(10);
var uniqueIds = manyFoos
.Select(x => x.PropertyToCustomize)
.Where(x => x.Length == 5)
.Distinct()
.ToArray();
Assert.AreEqual(10, uniqueIds.Length);
}
}
}
```
๊ถ์ฅ ์ฌํญ: GUID ๋ฌธ์์ด์์ ์ฒ์ _n_์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํด๋์ค ์ด๋ฆ์ UniqueShortGuidBuilder
์ง์ ํ์ง ๋ง์ญ์์ค. ๊ธธ์ด๊ฐ 5์ด๋ฉด ๊ฐ์ด ์๋นํ ๊ณ ์ ํ ์ ์์ง๋ง 1๋ก ์ค์ ํ๋ฉด ์ถฉ๋์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด์จ๋ ๊ณ ์ ์ฑ์ ๋ณด์ฅ๋์ง ์์ต๋๋ค.
๋ฌธ์์ด์ ๊ธธ์ด์ ๋ณด์ฅ๋์ง ์์ ๊ณ ์ ์ฑ์ ๊ด์ฌ์ด ์๋ค๋ฉด AutoFixture์ ์๋ฅผ ๋ค์ด 0์์ 99,999 ์ฌ์ด์ ์ซ์๋ฅผ ์์ฒญํ๊ณ ์ด๋ฅผ ๋ฌธ์์ด๋ก ๋ฐ๊พธ๋ฉด ์ด๋จ๊น์? IIRC, ์ซ์๋ ๋ฒ์๊ฐ ์์ง๋ ๋๊น์ง ๊ณ ์ ํฉ๋๋ค.
Fixture.Customize(new FooCustomization()); ํ ์คํธ๋ ํต๊ณผํ๊ณ ๊ทธ๋ ์ง ์์ผ๋ฉด ํต๊ณผํ์ง ๋ชปํฉ๋๋ค.
๋ญ, ์ฌ์ค ์ํฉ์ ์ ์ดํด๋ณด์๋ฉด ์์๋๋ ํ๋์
๋๋ค ๐ #962 ์์ ์ ๋ต๊ธ ์ ๋ด์ฃผ์ธ์. ์ ๊ณต๋ FooCustomization
๊ตฌํ์ Foo
์ ํ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ํญ์ ํด๋น ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋๋ก ์กฐ๋ช
๊ธฐ๋ฅผ ๊ตฌ์ฑํฉ๋๋ค. ๋ฐ๋ผ์ ๋์ค์ Foo
์ ํ์ ์ฌ๋ฌ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ๋ ๋์ผํ ๊ฐ์ฒด๊ฐ ๋ฐํ๋๊ณ ๋น๋๊ฐ ๋ ์ด์ ํธ์ถ๋์ง ์์ ๋๋ง๋ค.
Foo
๋ฅผ ์์ฒญํ ๋๋ง๋ค ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ค๋ฉด ์ฌ๊ธฐ์์ ์ ์ํ ๋๋ก Customize<>
API๋ฅผ ์ฌ์ฉ ํ์ญ์์ค .
@ploeh ํ์ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ํ์ง๋ง ๊ทธ ์ฝ๋๋ ํ ์คํธ ๋ชฉ์ ์ ์ํ ์ด์ฒด์ ์ธ ์์ผ ๋ฟ์ ๋๋ค. ์ค์ ๊ฒฝ์ฐ ๊ธธ์ด๋ Guids์ ๊ณ ์ ์ฑ์ ์ํฅ์ ์ค ์ ๋๋ก ์งง์ง ์์ต๋๋ค ๐.
๋ฌธ์์ด์ ๊ธธ์ด์ ๋ณด์ฅ๋์ง ์์ ๊ณ ์ ์ฑ์ ๊ด์ฌ์ด ์๋ค๋ฉด AutoFixture์ ์๋ฅผ ๋ค์ด 0์์ 99,999 ์ฌ์ด์ ์ซ์๋ฅผ ์์ฒญํ๊ณ ์ด๋ฅผ ๋ฌธ์์ด๋ก ๋ฐ๊พธ๋ฉด ์ด๋จ๊น์?
๋๋ ์ด๊ฒ์ด ๋๋ถ๋ถ์ ๊ฒฝ์ฐ์ ์ข์ ์๋ฃจ์ ์ด๋ผ๊ณ ํ์ ํ์ง๋ง ๋ด ์์คํ ์ ์์ซ์ ์ ํจ์ฑ ๊ฒ์ฌ ๋๋ฌธ์ ์ด ํน์ ํ ๊ฒฝ์ฐ์๋ ๊ทธ๋ ๊ฒ ํ ์ ์์ต๋๋ค. ๊ทธ ์ธ์๋ ํด๋น ํ๋์ ๊ด๋ จ๋ ๋ ๋ณต์กํ ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ์์ต๋๋ค.
๊ธ์์, ์ฌ์ค ์ํฉ์ ์ข ๋ ์์ธํ ์ดํด๋ณด๋ฉด ์์๋๋ ํ๋์ ๋๋ค.
@zvirja #962์์ ๋ต์ฅ์ ์ฌ๊ธฐ์ ์ง์ ํ ๊ฒ์ฒ๋ผ) ๊ทธ ํ๋์ด ๋ถ๋ช ํ์ง ์์์ต๋๋ค. ๐.
๋ง๋ฌด๋ฆฌ๋ก ์ธ๋ด์ฌ๊ณผ ๋ชจ๋ ํ๋ฅญํ ์ค๋ช
์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
๋๋ ์ด๊ฒ์ด ๋ฏธ๋์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ๋ ์ ์ฉํ ๊ฒ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค ๐.
์ข์, ์ถฉ๋ถํ ๊ณตํํ๊ฒ, ๋๋ ์ผ์ ๋๋ฌด ๋ฌธ์ ๊ทธ๋๋ก ๋ฐ์๋ค์ด๋ ๊ฒฝํฅ์ด ์์์ง๋ ๋ชจ๋ฅธ๋ค ๐