nickdodd79 / AutoBogus

A C# library complementing the Bogus generator by adding auto creation and population capabilities.
MIT License
431 stars 50 forks source link

Object of type 'System.Collections.Generic.List`1[System.String]' cannot be converted to type 'System.Collections.Generic.ISet`1[System.String]'. #25

Closed j-fritsch closed 4 years ago

j-fritsch commented 4 years ago

Starting in v2.7.0, I'm getting a list conversion error when setting an ISet property with a HashSet populated via an IList within a rule. This is not happening in v2.6.0.

public class MyClass
{
    public ISet<string> MySet { get; set; }
}
var faker = new AutoFaker<MyClass>()
    .RuleFor(o => o.MySet, f => new HashSet<string>(f.Make(3, () => f.Lorem.Word())));

var fakes = faker.Generate();

The generation throws the conversion error.

System.ArgumentException: 
  at at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
  at at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
  at at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
  at at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
  at at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
  at at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
  at at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
  at at AutoBogus.AutoMember.<>c__DisplayClass0_0.<.ctor>b__1(Object obj, Object value)
  at at AutoBogus.AutoBinder.PopulateInstance[TType](Object instance, AutoGenerateContext context, IEnumerable`1 members)
  at at AutoBogus.Generators.TypeGenerator`1.AutoBogus.IAutoGenerator.Generate(AutoGenerateContext context)
  at at AutoBogus.AutoFaker`1.<>c__DisplayClass30_0.<PrepareCreate>b__0(Faker faker)
  at at Bogus.Faker`1.Generate(String ruleSets)
  at at AutoBogus.AutoFaker`1.Generate(String ruleSets)
  at ConsoleApp1.Program.Main(String[] args) in /ConsoleApp1/ConsoleApp1/Program.cs:19
nickdodd79 commented 4 years ago

Hi.

The fact that the property is writable should mean you shouldn't go down that generation path. I will take a look and push out a fix.

Nick.

j-fritsch commented 4 years ago

Thanks, Nick!

nickdodd79 commented 4 years ago

Hey @j-fritsch

I have made a change and pushed v2.7.2. It now generates ISet<> types through a dedicated generator.

In theory you should have not been seeing that error as you have provided a RuleFor() for that property. My investigation has showed that the generation process could be optimized, so this is a great catch.

Thanks. Nick.

j-fritsch commented 4 years ago

Glad to hear it! Thank you for the quick response, I appreciate it!

j-fritsch commented 4 years ago

@nickdodd79, looks like IReadOnlyDictionary types aren't working on v2.7.2. Appears to have stopped working as of v2.7.0 as well.

public class MyClass
{
    public IReadOnlyDictionary<int, string> MyDictionary { get; set; }
}
var dictionary = new Dictionary<int, string>
{
    { 1, "value1" },
    { 2, "value2" }
};

var faker = new AutoFaker<MyClass>()
    .RuleFor(o => o.MyDictionary, f => dictionary);

var fakes = faker.Generate();

I'm getting this exception:

Unhandled exception. System.InvalidOperationException: Sequence contains more than one element
   at System.Linq.ThrowHelper.ThrowMoreThanOneElementException()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   at AutoBogus.AutoGeneratorFactory.ResolveGenerator(AutoGenerateContext context)
   at AutoBogus.AutoGeneratorFactory.GetGenerator(AutoGenerateContext context)
   at AutoBogus.AutoBinder.PopulateInstance[TType](Object instance, AutoGenerateContext context, IEnumerable`1 members)
   at AutoBogus.Generators.TypeGenerator`1.AutoBogus.IAutoGenerator.Generate(AutoGenerateContext context)
   at AutoBogus.AutoFaker`1.<>c__DisplayClass30_0.<PrepareCreate>b__0(Faker faker)
   at Bogus.Faker`1.Generate(String ruleSets)
   at AutoBogus.AutoFaker`1.Generate(String ruleSets)
   at ConsoleApp1.Program.Main(String[] args) in /ConsoleApp1/ConsoleApp1/Program.cs:line 26
nickdodd79 commented 4 years ago

Hey @j-fritsch

You have become the unofficial QA for the project šŸ˜„

I will take a look and get fix out. Also thinking I'm gonna add some more tests around all the different collection types, as they have their own paths through the generation process and need to the sanity checking.

Nick.

j-fritsch commented 4 years ago

šŸ˜›

Thanks, @nickdodd79! I just happened to be updating the dependencies in the project I am working on. Glad I can help.

nickdodd79 commented 4 years ago

Hey @j-fritsch

I just pushed v2.7.3 which adds a new generator for the IReadOnlyDictionary type.

Nick.

j-fritsch commented 4 years ago

All my tests are passing again. Thanks again, @nickdodd79, I appreciate the quick responses!