Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/GenFu/GenFu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ private static List<object> BuildList(Type type, int itemCount)

private static void SetPropertyValue(object instance, PropertyInfo property)
{
if (IgnorePropertyCollection.IsPropertyInIgnoreList(property))
return;
IPropertyFiller filler = _fillerManager.GetFiller(property);
property.SetValue(instance, filler.GetValue(instance), null);
}
Expand Down
30 changes: 27 additions & 3 deletions src/GenFu/GenFuConfigurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,13 @@ public GenFuConfigurator(GenFu genfu, FillerManager fillerManager)
{
}


private PropertyInfo GetPropertyInfoFromExpression<T2>(Expression<Func<T, T2>> expression)
{
PropertyInfo propertyInfo = (expression.Body as MemberExpression).Member as PropertyInfo;
return propertyInfo;
}

private MethodInfo GetMethodInfoFromExpression(Expression<Action<T>> expression)
{

Expand Down Expand Up @@ -263,9 +263,33 @@ public GenFuComplexPropertyConfigurator<T, T2> MethodFill<T2>(Expression<Action<
{
MethodInfo methodInfo = GetMethodInfoFromExpression(expression);
IPropertyFiller filler = _fillerManager.GetGenericFillerForType(methodInfo.GetParameters()[0].ParameterType);
PropertyFiller<T2> customFiller = new CustomFiller<T2>(methodInfo.Name, typeof(T), () => (T2)filler.GetValue(null));
PropertyFiller<T2> customFiller = new CustomFiller<T2>(methodInfo.Name, typeof(T), () => (T2)filler.GetValue(null));
_fillerManager.RegisterFiller(customFiller);
return new GenFuComplexPropertyConfigurator<T, T2>(_genfu, _fillerManager, methodInfo);
}

/// <summary>
/// Configure which property should be ignored while creating new object
/// </summary>
/// <param name="expression">Property on which needs to be ignored</param>
/// <returns></returns>
public GenFuConfigurator<T> Ignore(Expression<Func<T, object>> expression)
{
MemberInfo memberInfoOfIgnoredProperty;
if (expression.Body is MemberExpression)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
memberInfoOfIgnoredProperty = memberExpression.Member;
}
else
{
UnaryExpression unaryExpression = expression.Body as UnaryExpression;
MemberExpression memberExpression = unaryExpression.Operand as MemberExpression;
memberInfoOfIgnoredProperty = memberExpression.Member;
}
IgnorePropertyCollection.AddPropertyToIgnoreList(memberInfoOfIgnoredProperty);

return this;
}
}
}
2 changes: 2 additions & 0 deletions src/GenFu/GenFuFluent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,13 @@ public static void Reset()
defaults.SetSeedPercentage(GenFu.Defaults.SEED_PERCENTAGE);

ResourceLoader.PropertyFillers.Clear();
IgnorePropertyCollection.Reset();
}

public static void Reset<T>()
{
_fillerManager.ResetFillers<T>();
IgnorePropertyCollection.Reset<T>();

}

Expand Down
108 changes: 108 additions & 0 deletions src/GenFu/IgnorePropertyCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;

namespace GenFu
{
/// <summary>
/// Helps in managing the properties which we should not be initialized while creating new object,
/// Reference types will be null, and value type properties will have default value unless those are nullable
/// </summary>
public static class IgnorePropertyCollection
{
private static Dictionary<Type, List<string>> _propertiesToIgnore;
private static ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
static IgnorePropertyCollection()
{
_propertiesToIgnore = new Dictionary<Type, List<string>>();
}

/// <summary>
/// Property which will be ignored for initialization during new object creation
/// </summary>
/// <param name="memberInfo">Property to be ignored</param>
public static void AddPropertyToIgnoreList(MemberInfo memberInfo)
{
try
{
_readWriteLock.EnterWriteLock();
if (!_propertiesToIgnore.ContainsKey(memberInfo.DeclaringType))
{
var fieldCollection = new List<string>
{
memberInfo.Name
};
_propertiesToIgnore.Add(memberInfo.DeclaringType, fieldCollection);
}
else
{
if (!_propertiesToIgnore[memberInfo.DeclaringType].Contains(memberInfo.Name))
_propertiesToIgnore[memberInfo.DeclaringType].Add(memberInfo.Name);
}
}
finally
{
_readWriteLock.ExitWriteLock();
}
}

/// <summary>
/// Checks whether given <paramref name="propertyInfo"/> needs to be ignored or not
/// </summary>
/// <param name="propertyInfo"></param>
/// <returns></returns>
public static bool IsPropertyInIgnoreList(PropertyInfo propertyInfo)
{
try
{
_readWriteLock.EnterReadLock();
if (!_propertiesToIgnore.ContainsKey(propertyInfo.DeclaringType))
return false;

List<string> fieldCollection = _propertiesToIgnore[propertyInfo.DeclaringType];
return fieldCollection.Contains(propertyInfo.Name);
}
finally
{
_readWriteLock.ExitReadLock();
}
}

/// <summary>
/// Removes all the properties from Ignore list of all Type
/// </summary>
public static void Reset()
{
try
{
_readWriteLock.EnterWriteLock();
_propertiesToIgnore = new Dictionary<Type, List<string>>();
}
finally
{
_readWriteLock.ExitWriteLock();
}
}

/// <summary>
/// Removes all the properties from Ignore list of the given Type
/// </summary>
/// <typeparam name="T"></typeparam>
public static void Reset<T>()
{
try
{
_readWriteLock.EnterWriteLock();
if (_propertiesToIgnore.ContainsKey(typeof(T)))
{
_propertiesToIgnore.Remove(typeof(T));
}
}
finally
{
_readWriteLock.ExitWriteLock();
}
}
}
}
136 changes: 136 additions & 0 deletions tests/GenFu.Tests/IgnorePropertyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using GenFu.Tests.TestEntities;
using System.Collections.Generic;
using Xunit;

namespace GenFu.Tests
{
public class IgnorePropertyTests
{
[Fact]
public void IgnoreStringField()
{
A.Reset<Person>();
A.Configure<Person>()
.Ignore(x => x.FirstName);

var person = A.New<Person>();
Assert.Null(person.FirstName);
}

[Fact]
public void IgnoreIntField()
{
A.Reset<Person>();
A.Configure<Person>()
.Ignore(x => x.Id);

var person = A.New<Person>();
Assert.Equal(default, person.Id);
}

[Fact]
public void IgnoreDateTimeField()
{
A.Reset<Person>();
A.Configure<Person>()
.Ignore(x => x.BirthDate)
.Ignore(x => x.DateOfDeath);

var person = A.New<Person>();
Assert.Null(person.DateOfDeath);
Assert.Equal(default, person.BirthDate);
}

[Fact]
public void IgnoreGuidField()
{
A.Reset<ApplicationUser>();
A.Configure<ApplicationUser>()
.Ignore(x => x.Id);

var applicationUser = A.New<ApplicationUser>();
Assert.Equal(default, applicationUser.Id);
}

[Fact]
public void IgnoreNullableFields()
{
A.Reset<Nullables>();
A.Configure<Nullables>()
.Ignore(x => x.NullableBoolean)
.Ignore(x => x.NullableChar)
.Ignore(x => x.NullableDateTime)
.Ignore(x => x.NullableDecimal)
.Ignore(x => x.NullableDouble)
.Ignore(x => x.NullableInt)
.Ignore(x => x.NullableLong)
.Ignore(x => x.NullableShort)
.Ignore(x => x.NullableUInt)
.Ignore(x => x.NullableULong);

var nullableObject = A.New<Nullables>();

Assert.Null(nullableObject.NullableBoolean);
Assert.Null(nullableObject.NullableChar);
Assert.Null(nullableObject.NullableDateTime);
Assert.Null(nullableObject.NullableDecimal);
Assert.Null(nullableObject.NullableDouble);
Assert.Null(nullableObject.NullableInt);
Assert.Null(nullableObject.NullableLong);
Assert.Null(nullableObject.NullableShort);
Assert.Null(nullableObject.NullableUInt);
Assert.Null(nullableObject.NullableULong);
}

[Fact]
public void IgnoreEnumField()
{
A.Reset();
A.Configure<BlogPost>()
.Ignore(x => x.Type);

var blogPost = A.New<BlogPost>();
Assert.Equal(default, blogPost.Type);
}

[Fact]
public void IgnoreConstructorInitializedCollectionField()
{
A.Reset();
A.Configure<BlogPost>()
.Ignore(x => x.Tags);

var blogPost = A.New<BlogPost>();
Assert.Equal(new HashSet<string>(), blogPost.Tags);
}

[Fact]
public void IgnoreUnInitializedCollectionField()
{
A.Reset();
var postcomments = A.ListOf<BlogComment>();

A.Configure<BlogPost>()
.Fill(b => b.Comments, () => postcomments)
.Ignore(x => x.Comments);
var blogPost = A.New<BlogPost>();

Assert.Equal(default, blogPost.Comments);
}

[Fact]
public void IgnoreMultipleFields()
{
A.Reset<Person>();
A.Configure<Person>()
.Ignore(x=>x.NumberOfToes)
.Ignore(x => x.LastName)
.Ignore(x => x.FirstName);

var person = A.New<Person>();
Assert.Equal(default, person.NumberOfToes);
Assert.Null(person.LastName);
Assert.Null(person.FirstName);
}
}
}
52 changes: 52 additions & 0 deletions tests/GenFu.Tests/IgnorePropertyWithResetTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using GenFu.Tests.TestEntities;
using Xunit;

namespace GenFu.Tests
{
public class IgnorePropertyWithResetTests
{
public IgnorePropertyWithResetTests()
{
A.Configure<Person>()
.Ignore(x => x.FirstName);
}
[Fact]
public void WhenResetNotCalled()
{
var person = A.New<Person>();
Assert.Null(person.FirstName);
}

[Fact]
public void WhenResetPersonCalled()
{
A.Reset<Person>();
var person = A.New<Person>();
Assert.NotNull(person.FirstName);
}

[Fact]
public void WhenResetCalled()
{
A.Reset();
var person = A.New<Person>();
Assert.NotNull(person.FirstName);
}

[Fact]
public void WhenResetCalledForOneType()
{
A.Configure<ApplicationUser>()
.Ignore(x => x.UserName);

//It will only reset the ignore properties of Person decalred in constructor
A.Reset<Person>();

var person = A.New<Person>();
var applicationUser = A.New<ApplicationUser>();

Assert.NotNull(person.FirstName);
Assert.Null(applicationUser.UserName);
}
}
}