nickdodd79 / AutoBogus

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

AutoFaker for HttpMethod has System.FormatException : The format of the HTTP method is invalid. #72

Closed kevinlo closed 3 years ago

kevinlo commented 3 years ago

I have a class that has HttpMethod as the constructor parameter

When I use the AutoFaker to generate it as follows, it has the System.FormatException randomly

            var requests = new AutoFaker<MyRequest>>()
                .RuleFor(x => x.Method, x => HttpMethod.Post)
                .RuleFor(x => x.Uri, x => BaseUrl)
                .Generate(2);

The problem is the HttpMethod constructor has the method string parameter and the StringGenerator can generate a string with space inside that cause FormatException when it compares the token

        public HttpMethod(string method)
        {
            if (string.IsNullOrEmpty(method))
            {
                throw new ArgumentException(SR.net_http_argument_empty_string, nameof(method));
            }
            if (HttpRuleParser.GetTokenLength(method, 0) != method.Length)
            {
                throw new FormatException(SR.net_http_httpmethod_format_error);
            }
            _method = method;
        }

e.g. as shown in this screen shot, the generated string "Zambian Kwacha" has space in it

image

I have tried using AutoGeneratorOverride derived class, but it does not help.

The problem is the AutoGenerateOverrideContext will create a default HttpMethod first before it applies to rule.

    object IAutoGenerator.Generate(AutoGenerateContext context)
    {
      var overrideContext = new AutoGenerateOverrideContext(context);

      foreach (var generatorOverride in Overrides)
      {
        // Check if an initialized instance is needed
        if (generatorOverride.Preinitialize && overrideContext.Instance == null)
        {
          overrideContext.Instance = Generator.Generate(context);
        }

        // Let each override apply updates to the instance
        generatorOverride.Generate(overrideContext);
      }      

      return overrideContext.Instance;
    }

Is there any workaround to solve it?

Before, the uri is in string type and it has the same problem when the uri is passsed to the Url constructor. I am forced to change the type from string to Url as there is a UriGenerator, But there is not HttpMethodGenerator. Is there a way to put a custom HttpMethodGenerator?

nickdodd79 commented 3 years ago

Hey @kevinlo

With overrides, there is a virtual Preinitialize property you can override to specify whether an initial value should be created. Did you set that false in your override implementation? If not, give that a try and we can work from there to see whether any other workarounds exist, or whether a change is needed in AutoBogus.

Nick.

kevinlo commented 3 years ago

@nickdodd79 Thanks for you suggestion. It works.

For those who has the similar problem, here is what I do. Please comment if anything is wrong.

    public class HttpMethodOverride : AutoGeneratorOverride
    {
        public override bool Preinitialize
        {
            get => false;
        }

        public override bool CanOverride(AutoGenerateContext context)
        {
            return context.GenerateType == typeof(HttpMethod);
        }

        public override void Generate(AutoGenerateOverrideContext context)
        {
           //  It generates a POST method, you can change to what you what and can use RuleFor to replace it
            context.Instance = HttpMethod.Post;
        }
    }

Call this in the test constructor

AutoFaker.Configure(builder => builder.WithOverride(new HttpMethodOverride());

Then the AutoFaker.Generate will generate the HttpMethod.POST by default:

var requests = AutoFaker.Generate<MyRequest>(2);