Tynamix / ObjectFiller.NET

The .NET ObjectFiller fills the properties of your .NET objects with random data
http://objectfiller.net
MIT License
76 stars 35 forks source link

Object reference not set to instance of an object when using records #136

Closed coeur85 closed 2 years ago

coeur85 commented 2 years ago

i prefer to use records when it comes data modeling, class for brokers and services.

i'm trying to use filler with public record and it's always throws an exception.

when i switched my model to class it worked like a charm, any way i can go around this ?

HerrLoesch commented 2 years ago

I have an idea but could you please provide us with more information. The exception type and message would be helpful.

essieessara commented 2 years ago

I have the same error object filler the repo to be checked https://github.com/essieessara/ObjectFiller.app.git

coeur85 commented 2 years ago

I have the same error object filler the repo to be checked https://github.com/essieessara/ObjectFiller.app.git

@HerrLoesch if you changed the model type from class to record that should break things

HerrLoesch commented 2 years ago

Today I had a short look into the problem: Reason for this bug is, that records are immutable classes or structs. Till this point we always created an instance of a class or struct and set then its properties. Records have no setter thus the setter method we get from the framework is simply null and causes the error. This seems to make a bigger change to the filler necessary which is also a bit tricky because there does not seem to be an official way of getting the information if a type is actually a record or not.

Tynamix commented 2 years ago

@HerrLoesch i also thought it would be hard but then i read this: https://www.meziantou.net/csharp9-init-only-properties-are-not-read-only.htm Seems to me like records are only code sugar at least for the reflection api.

I changed this line of code https://github.com/Tynamix/ObjectFiller.NET/blob/40870dae6ab2cc318da63dd700409d0a8e11d080/Tynamix.ObjectFiller/NetTypeApiExtension.cs#L40 to

return source?.SetMethod; 

to avoid the object reference error and it works and all unit tests are running

I wrote this unit test:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

#if NET6_0_OR_GREATER
namespace Tynamix.ObjectFiller.Test.BugfixTests
{
    public record Product
    {
        public string Name { get; init; }
        public int CategoryId { get; set; }
    }

    public record Person(string Name, string Username);

    [TestClass]
    public class Bug136RecordsObjectReferenceException
    {
        [TestMethod]
        public void RecordsShouldBeFilled()
        {
            Filler<Product> filler = new Filler<Product>();
            var product = filler.Create();
            Assert.IsNotNull(product);
            Assert.IsFalse(string.IsNullOrWhiteSpace(product.Name));

            var filler2 = new Filler<Person>();
            var person = filler2.Create();
            Assert.IsNotNull(person);
            Assert.IsFalse(string.IsNullOrWhiteSpace(person.Name));
            Assert.IsFalse(string.IsNullOrWhiteSpace(person.Username));
        }
    }
}
#endif
HerrLoesch commented 2 years ago

Did not expect it to set the value without a setter method :D

Tynamix commented 2 years ago

released https://www.nuget.org/packages/Tynamix.ObjectFiller/1.5.8 with support for records.