I'm trying to craft a unit test that will check for a given assembly that all non-abstract classes with empty constructors will instantiate their collection properties when instantiated. Here's the system under test:
namespace MyProject.Dto.Things
{
public class Item
{
public Item()
{
// Second batch of props should be instantiated here...
}
// Properties that my test doesn't/shouldn't care about:
public int IntProp { get; set; }
public string StringProp { get; set; }
// Properties my test should account for:
public List<string> ListProp { get; set; }
public IList<string> IListProp { get; set; }
public ISet<string> ISetProp { get; set; }
public ICollection<string> ICollectionProp { get; set; }
public IDictionary<string, string> IDictionaryProp { get; set; }
public Stack<string> StackProp { get; set; }
public string[] ArrayProp { get; set; }
}
}
My first attempt whas this:
[TestFixture]
public class DtoTests
{
[Test]
public void NamespaceDtos_WhenDefaultConstructorIsCalled_InstantiatesCollectionProperties()
{
bool testWasMeaningful = false;
foreach (var type in GetEntityTypesWithDefaultConstructor())
{
var instance = Activator.CreateInstance(type);
var collectionProps = type
.GetProperties()
.Where(p => typeof(ICollection<>).IsAssignableFrom(p.PropertyType));
foreach (var prop in collectionProps)
{
var val = prop.GetValue(instance);
Assert.That(val, Is.Not.Null.And.Empty, string.Format("[{0}.{1}]", type.Name, prop.Name));
testWasMeaningful = true;
}
}
Assert.That(testWasMeaningful, "Expected at least one assertion.");
}
private IEnumerable<Type> GetEntityTypesWithDefaultConstructor()
{
return Assembly
.GetAssembly(typeof(MyProject.Dto.Things.Item))
.GetTypes()
.Where(t => !t.IsAbstract)
.Where(t => t.GetConstructor(Type.EmptyTypes) != null);
}
}
However, this does not work, because the Where
clause does not grab the correct properties from my other assembly. My test fails because it tests not a single property.
Attempted fix no 1
I've tried this answer like this:
var collectionProps = type
.GetProperties()
.Where(m => m.PropertyType.IsGenericType && m.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>));
But that only catches Item.ICollectionProp
, and fails to test all others.
Attempted fix no 2
Second, I've tried this answer to another question (using the GetICollectionOrICollectionOfTProperties
method ad verbatim), like this:
var collectionProps = type
.GetICollectionOrICollectionOfTProperties();
But ironically, that will incorrectly pass the test even if Item.ICollectionProp
is not instantiated.
Attempted fix no 3
I've also tried testing just all IEnumerable
properties, like this:
var collectionProps = type
.GetProperties()
.Where(p => typeof(IEnumerable).IsAssignableFrom(p.PropertyType));
But that will fail on Item.StringProp
, because string
is IEnumerable
, and I do not want to test for that here.
I'm not sure where I go wrong, especially with nr 2. I'd even think my question is a duplicate of that one, if I'd only had gotten the solution to work.
Bottom line: (X) how can I test that all collection properties of classes with empty constructors are instantiated when the class is instantiated, and/or (Y) how can I find all collection properties of a type using reflection?
Aucun commentaire:
Enregistrer un commentaire