How to generate json text field with random numeric content #486

Closed
opened 2025-12-29 15:24:54 +01:00 by adam · 24 comments
Owner

Originally created by @robertmircea on GitHub (Feb 12, 2023).

Originally assigned to: @StefH on GitHub.

I am trying to generate a json string field with random integers inside using response templating. Unfortunately, I cannot obtain the expected reply:

    var server = StandAloneApp.Start(settings);
    server.Given(Request.Create()
        .WithPath("/profile")
        .UsingGet()
    ).RespondWith(Response.Create()
        .WithTransformer()
        .WithBodyAsJson(new
        {
            puk = "{{Random Type=\"Integer\" Min=0 Max=2000000}}",
        })

produces a numeric field instead of a string:

{
      "puk": 1638351854,
}

instead of

{
      "puk": "1638351854",
}

How can I generate a random integer with min/max constraints formatted as a string?
Alternatively, I've tried "{{Random Type=\"TextRegex\" Pattern=\"[0-9]{10}\"}}" and the result is the same: numeric json field instead of string. It seems that the library is converting automatically any numeric string to numeric field value.

Originally created by @robertmircea on GitHub (Feb 12, 2023). Originally assigned to: @StefH on GitHub. I am trying to generate a json string field with random integers inside using response templating. Unfortunately, I cannot obtain the expected reply: ```cs var server = StandAloneApp.Start(settings); server.Given(Request.Create() .WithPath("/profile") .UsingGet() ).RespondWith(Response.Create() .WithTransformer() .WithBodyAsJson(new { puk = "{{Random Type=\"Integer\" Min=0 Max=2000000}}", }) ``` produces a numeric field instead of a string: ```json { "puk": 1638351854, } ``` instead of ```json { "puk": "1638351854", } ``` How can I generate a random integer with min/max constraints formatted as a string? Alternatively, I've tried `"{{Random Type=\"TextRegex\" Pattern=\"[0-9]{10}\"}}"` and the result is the same: numeric json field instead of string. It seems that the library is converting automatically any numeric string to numeric field value.
adam added the question label 2025-12-29 15:24:54 +01:00
adam closed this issue 2025-12-29 15:24:54 +01:00
Author
Owner

@StefH commented on GitHub (Feb 12, 2023):

Did you try adding \"?

puk = "\"{{Random Type=\"Integer\" Min=0 Max=2000000}}\"",
@StefH commented on GitHub (Feb 12, 2023): Did you try adding `\"`? ``` C# puk = "\"{{Random Type=\"Integer\" Min=0 Max=2000000}}\"", ```
Author
Owner

@robertmircea commented on GitHub (Feb 12, 2023):

It formats like this:

HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 12 Feb 2023 10:20:15 GMT
Server: Kestrel
Transfer-Encoding: chunked

{
    "puk": "\"98039567\"",
}
@robertmircea commented on GitHub (Feb 12, 2023): It formats like this: ```http HTTP/1.1 200 OK Content-Type: application/json Date: Sun, 12 Feb 2023 10:20:15 GMT Server: Kestrel Transfer-Encoding: chunked { "puk": "\"98039567\"", } ```
Author
Owner

@StefH commented on GitHub (Mar 9, 2023):

Hello @robertmircea , did you have time to verify this?

@StefH commented on GitHub (Mar 9, 2023): Hello @robertmircea , did you have time to verify this?
Author
Owner

@StefH commented on GitHub (Mar 21, 2023):

Hello @robertmircea , did you have time to verify this?

@StefH commented on GitHub (Mar 21, 2023): Hello @robertmircea , did you have time to verify this?
Author
Owner

@StefH commented on GitHub (May 12, 2023):

Hello @robertmircea , did you have time to verify this?

@StefH commented on GitHub (May 12, 2023): Hello @robertmircea , did you have time to verify this?
Author
Owner

@maivanquanbk commented on GitHub (Aug 25, 2023):

Hi @StefH, when can I expect to have this feature? Thanks a lot

@maivanquanbk commented on GitHub (Aug 25, 2023): Hi @StefH, when can I expect to have this feature? Thanks a lot
Author
Owner

@StefH commented on GitHub (Nov 1, 2023):

@maivanquanbk
Did you have time to check that preview?

@StefH commented on GitHub (Nov 1, 2023): @maivanquanbk Did you have time to check that preview?
Author
Owner

@felipetofoli commented on GitHub (Dec 8, 2023):

As described in the issue #1028 , I am facing the same situation when parsing a DateTime "{{ DateTime.UtcNow \"yyMMddhhmmss\" }}" (after opening the issue I noticed the same applies for other dynamic fields, like outputs that resulted from lookup operation, etc.).

Just adding the comment here, so I can be notified with updates about this issue.

@felipetofoli commented on GitHub (Dec 8, 2023): As described in the issue #1028 , I am facing the same situation when parsing a DateTime `"{{ DateTime.UtcNow \"yyMMddhhmmss\" }}"` (after opening the issue I noticed the same applies for other dynamic fields, like outputs that resulted from `lookup` operation, etc.). Just adding the comment here, so I can be notified with updates about this issue.
Author
Owner

@StefH commented on GitHub (Dec 9, 2023):

https://github.com/WireMock-Net/WireMock.Net/pull/1036

@StefH commented on GitHub (Dec 9, 2023): https://github.com/WireMock-Net/WireMock.Net/pull/1036
Author
Owner

@StefH commented on GitHub (Dec 9, 2023):

@robertmircea
@maivanquanbk
@felipetofoli

I've decided to change the logic as follows:

  1. By default, the value from Random or DateTime.Now or another Handlebars function will be converted to a primitive type. This is done to not break current functionality.

    So for example when a value can be converted to a string, it will be converted.

  2. If you do not want this, use this c# code : .WithTransformer(ReplaceNodeOptions.Evaluate)
    This will generate the puk code like:

    {
      "puk": "98039567"
    }
    

    And the timestamps like:

    {
      "timestamp": "231205110312",
      "timestamp2": "231205110312",
      "timestamp3": "231205110312"
    }
    

A preview version with this logic is : 1.5.42-ci-18041

@StefH commented on GitHub (Dec 9, 2023): @robertmircea @maivanquanbk @felipetofoli I've decided to change the logic as follows: 1. By **default**, the value from Random or DateTime.Now or another Handlebars function will be **converted** to a primitive type. This is done to not break current functionality. So for example when a value **can** be converted to a string, it **will** be converted. 2. If you do not want this, use this c# code : `.WithTransformer(ReplaceNodeOptions.Evaluate)` This will generate the puk code like: ``` json { "puk": "98039567" } ``` And the timestamps like: ``` json { "timestamp": "231205110312", "timestamp2": "231205110312", "timestamp3": "231205110312" } ``` A preview version with this logic is : `1.5.42-ci-18041`
Author
Owner

@felipetofoli commented on GitHub (Dec 11, 2023):

Hi @StefH , thanks for providing this new preview version!

I believe in topic 1. you meant: "So for example when a value can be converted to a primitive type, it will be converted.", right?

I tested the preview package and I received the timestamps as a string when applying the ReplaceNodeOptions.Evaluate option!


A question: What if we have a scenario where we need different behaviors at the "property" level?

Example: We need to return the current timestamp as a string, but a random number as an integer

{
    "timestamp": "20231211",
    "randomNumber": 358
}

How can we achieve the above result?
Maybe it would be interesting to have a way to convert(cast), format or force a certain type at the "property" level?
What do you think?

@felipetofoli commented on GitHub (Dec 11, 2023): Hi @StefH , thanks for providing this new preview version! I believe in topic `1.` you meant: "So for example when a value **can** be converted to a **primitive** type, it will be converted.", right? I tested the preview package and I received the timestamps as a string when applying the `ReplaceNodeOptions.Evaluate` option! --- A question: What if we have a scenario where we need different behaviors at the "property" level? Example: We need to return the current timestamp as a string, but a random number as an integer ``` { "timestamp": "20231211", "randomNumber": 358 } ``` How can we achieve the above result? Maybe it would be interesting to have a way to convert(cast), format or force a certain type at the "property" level? What do you think?
Author
Owner

@StefH commented on GitHub (Dec 12, 2023):

@felipetofoli

"So for example when a value can be converted to a primitive type, it will be converted.", right?
Correct, if the string value is not any of the supported types, it will not be converted. So the string "abc" will not be converted to an integer.


I understand your request, I'm working on this, but it's difficult because the return value from Handlebars is always a string.

I'm working on a work-around :
Adding an Handlebars method named String.FormatAsString which you can use to convert the string to a wrapped / encoded string value which can be understood by WireMock so that in that case, no automatic conversion will be attempted.

A unit test for this could be:

    [Theory]
    [InlineData(ReplaceNodeOptions.EvaluateAndTryToConvert)]
    [InlineData(ReplaceNodeOptions.Evaluate)]
    public async Task Response_WithBodyAsJson_ProvideResponseAsync_Handlebars_DateTimeWithStringFormatAsString(ReplaceNodeOptions options)
    {
        // Assign
        var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);

        var responseBuilder = Response.Create()
            .WithBodyAsJson(new
            {
                FormatAsString = "{{ String.FormatAsString (DateTime.UtcNow) \"yyMMddhhmmss\" }}"
            })
            .WithTransformer(options);

        // Act
        var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);

        // Assert
        var jObject = JObject.FromObject(response.Message.BodyData!.BodyAsJson!);
        jObject["FormatAsString"]!.Type.Should().Be(JTokenType.String);
    }

However I need to think some more on this.

Maybe also a another method like Object.FormatAsValue should be added to always make sure that the string value is converted to a supported type....

@StefH commented on GitHub (Dec 12, 2023): @felipetofoli > "So for example when a value can be converted to a primitive type, it will be converted.", right? Correct, if the string value is not any of the supported types, it will not be converted. So the string "abc" will not be converted to an integer. --- I understand your request, I'm working on this, but it's difficult because the return value from Handlebars is always a string. I'm working on a work-around : Adding an Handlebars method named `String.FormatAsString` which you can use to convert the string to a wrapped / encoded string value which can be understood by WireMock so that in that case, no automatic conversion will be attempted. A unit test for this could be: ``` c# [Theory] [InlineData(ReplaceNodeOptions.EvaluateAndTryToConvert)] [InlineData(ReplaceNodeOptions.Evaluate)] public async Task Response_WithBodyAsJson_ProvideResponseAsync_Handlebars_DateTimeWithStringFormatAsString(ReplaceNodeOptions options) { // Assign var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp); var responseBuilder = Response.Create() .WithBodyAsJson(new { FormatAsString = "{{ String.FormatAsString (DateTime.UtcNow) \"yyMMddhhmmss\" }}" }) .WithTransformer(options); // Act var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); // Assert var jObject = JObject.FromObject(response.Message.BodyData!.BodyAsJson!); jObject["FormatAsString"]!.Type.Should().Be(JTokenType.String); } ``` However I need to think some more on this. Maybe also a another method like `Object.FormatAsValue` should be added to always make sure that the string value is converted to a supported type....
Author
Owner

@felipetofoli commented on GitHub (Dec 12, 2023):

Thanks for your quick reply, @StefH !
Yes, this approach (at the property level) is flexible and it seems interesting!
Let me know if I can help you with anything!
Thanks!

@felipetofoli commented on GitHub (Dec 12, 2023): Thanks for your quick reply, @StefH ! Yes, this approach (at the property level) is flexible and it seems interesting! Let me know if I can help you with anything! Thanks!
Author
Owner

@StefH commented on GitHub (Dec 15, 2023):

Thanks for your quick reply, @StefH ! Yes, this approach (at the property level) is flexible and it seems interesting! Let me know if I can help you with anything! Thanks!

You can test preview 1.5.43-ci-18089

@StefH commented on GitHub (Dec 15, 2023): > Thanks for your quick reply, @StefH ! Yes, this approach (at the property level) is flexible and it seems interesting! Let me know if I can help you with anything! Thanks! You can test preview 1.5.43-ci-18089
Author
Owner

@felipetofoli commented on GitHub (Dec 19, 2023):

You can test preview 1.5.43-ci-18089

Hi @StefH !
I tested and the timestamps are returned as a string when using .WithTransformer(ReplaceNodeOptions.Evaluate).

Is there anything else I should test? Am I missing any new scenario that was implemented in this preview release?

@felipetofoli commented on GitHub (Dec 19, 2023): > You can test preview 1.5.43-ci-18089 Hi @StefH ! I tested and the timestamps are returned as a `string` when using `.WithTransformer(ReplaceNodeOptions.Evaluate)`. Is there anything else I should test? Am I missing any new scenario that was implemented in this preview release?
Author
Owner

@felipetofoli commented on GitHub (Dec 19, 2023):

I checked the Handlebars repo, and I noticed that the String.FormatAsString method was implemented.
The String.FormatAsString is working! 😃

Test

Server config

server
    .Given(Request
            .Create()
            .WithPath(new ExactMatcher("/some-path"))
            .UsingPost())
    .RespondWith(Response
        .Create()
        .WithHeader("Content-Type", "application/json")
        .WithBodyAsJson(new
        {
            timestamp_number = "{{ DateTime.UtcNow \"yyMMddhhmmss\" }}",
            timestamp_string = "{{ String.FormatAsString (DateTime.UtcNow) \"yyMMddhhmmss\" }}"
        })
        .WithTransformer());

Response

{
    "timestamp_number": 231219053551,
    "timestamp_string": "231219053551"
}

Question

For a scenario where we don't have to specify a format (like a simple ToString()), is the expected passing an empty string?
Or we would like to have a new overload without a "format" param ({{ String.FormatAsString (request.PathSegments.[3]) }})?

.RespondWith(Response
    .Create()
    .WithHeader("Content-Type", "application/json")
    .WithBodyAsJson(new
    {
        somedata = new
        {
            frompath = "{{ String.FormatAsString (request.PathSegments.[3]) '' }}"
        }
    })
    .WithTransformer());
@felipetofoli commented on GitHub (Dec 19, 2023): I checked the Handlebars repo, and I noticed that the `String.FormatAsString` method was implemented. The `String.FormatAsString` is working! :smiley: ### Test #### Server config ```csharp server .Given(Request .Create() .WithPath(new ExactMatcher("/some-path")) .UsingPost()) .RespondWith(Response .Create() .WithHeader("Content-Type", "application/json") .WithBodyAsJson(new { timestamp_number = "{{ DateTime.UtcNow \"yyMMddhhmmss\" }}", timestamp_string = "{{ String.FormatAsString (DateTime.UtcNow) \"yyMMddhhmmss\" }}" }) .WithTransformer()); ``` #### Response ``` { "timestamp_number": 231219053551, "timestamp_string": "231219053551" } ``` --- ### Question For a scenario where we don't have to specify a format (like a simple `ToString()`), is the expected passing an empty string? Or we would like to have a new overload without a "format" param (`{{ String.FormatAsString (request.PathSegments.[3]) }}`)? ```csharp .RespondWith(Response .Create() .WithHeader("Content-Type", "application/json") .WithBodyAsJson(new { somedata = new { frompath = "{{ String.FormatAsString (request.PathSegments.[3]) '' }}" } }) .WithTransformer()); ```
Author
Owner

@StefH commented on GitHub (Dec 19, 2023):

I think you can just omit the format. No need for passing an empty string.

Can you try that?

@StefH commented on GitHub (Dec 19, 2023): I think you can just omit the format. No need for passing an empty string. Can you try that?
Author
Owner

@felipetofoli commented on GitHub (Dec 19, 2023):

I think you can just omit the format. No need for passing an empty string.

Can you try that?

I'd tried that. It's not possible.

Test

Server config

somedata = new
{
    frompath = "{{ String.FormatAsString (request.PathSegments.[3]) }}"
}

Response

HTTP/1.1 500 Internal Server Error 
{"Status":"The String.FormatAsString helper must have exactly 2 arguments."}
@felipetofoli commented on GitHub (Dec 19, 2023): > I think you can just omit the format. No need for passing an empty string. > > Can you try that? I'd tried that. It's not possible. ### Test #### Server config ```csharp somedata = new { frompath = "{{ String.FormatAsString (request.PathSegments.[3]) }}" } ``` #### Response ``` HTTP/1.1 500 Internal Server Error {"Status":"The String.FormatAsString helper must have exactly 2 arguments."} ```
Author
Owner

@StefH commented on GitHub (Dec 20, 2023):

@felipetofoli
I see, this is not yet supported.

I've update Handlebars.Net.Helpers (https://github.com/Handlebars-Net/Handlebars.Net.Helpers/pull/87) and I'll release a new NuGet and build a new preview for WireMock.Net

Stay tuned....

@StefH commented on GitHub (Dec 20, 2023): @felipetofoli I see, this is not yet supported. I've update Handlebars.Net.Helpers (https://github.com/Handlebars-Net/Handlebars.Net.Helpers/pull/87) and I'll release a new NuGet and build a new preview for WireMock.Net Stay tuned....
Author
Owner

@felipetofoli commented on GitHub (Dec 20, 2023):

@StefH
Thanks for all your support! 😃

@felipetofoli commented on GitHub (Dec 20, 2023): @StefH Thanks for all your support! 😃
Author
Owner

@StefH commented on GitHub (Dec 20, 2023):

Can you try preview 1.5.43-ci-18158 ?

@StefH commented on GitHub (Dec 20, 2023): Can you try preview 1.5.43-ci-18158 ?
Author
Owner

@felipetofoli commented on GitHub (Dec 21, 2023):

Can you try preview 1.5.43-ci-18158 ?

@StefH I tried the preview package:

Tests

EvaluateAndTryToConvert (or default: .WithTransformer())

server
    .Given(Request
        .Create()
        .WithPath(new ExactMatcher("/type-conversion"))
        .UsingPost())
    .RespondWith(Response
        .Create()
        .WithHeader("Content-Type", "application/json")
        .WithBodyAsJson(new
        {
            timestamp = "{{ DateTime.UtcNow \"yyMMddhhmmss\" }}",
            timestamp_as_string = "{{ String.FormatAsString (DateTime.UtcNow) \"yyMMddhhmmss\" }}",
            timestamp_as_string_without_format = "{{ String.FormatAsString (DateTime.UtcNow) }}",

            random_number = "{{ Random Type='Integer' Min=1 Max=100 }}",
            random_number_as_number = "{{ Object.FormatAsObject (Random Type='Integer' Min=1 Max=100) }}",
            random_number_as_string = "{{ String.FormatAsString (Random Type='Integer' Min=1 Max=100) }}",

            number_from_body = "{{ request.bodyAsJson.number }}",
            number_from_body_as_number = "{{ Object.FormatAsObject (request.bodyAsJson.number) }}",
            number_from_body_as_string = "{{ String.FormatAsString (request.bodyAsJson.number) }}",

            numeric_string_from_body = "{{ request.bodyAsJson.numeric_string }}",
            numeric_string_from_body_as_number = "{{ Object.FormatAsObject (request.bodyAsJson.numeric_string) }}",
            numeric_string_from_body_as_string = "{{ String.FormatAsString (request.bodyAsJson.numeric_string) }}",
        })
        .WithTransformer(WireMock.Types.ReplaceNodeOptions.EvaluateAndTryToConvert));

HTTP Request/Response:

POST /type-conversion HTTP/1.1
Content-Type: application/json

{
  "number" : 999,
  "numeric_string": "011"
}
 
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 21 Dec 2023 18:10:08 GMT
 
{
 
 "timestamp":231221061008, 
 "timestamp_as_string":"231221061008",
 "timestamp_as_string_without_format":"21/12/2023 18:10:08",
 "random_number":43,
 "random_number_as_number":8,
 "random_number_as_string":"2",
 "number_from_body":999,
 "number_from_body_as_number":999,
 "number_from_body_as_string":"999",
 "numeric_string_from_body":"011",
 "numeric_string_from_body_as_number":11,
 "numeric_string_from_body_as_string":"011"
}

Evaluate

server
    .Given(Request
        .Create()
        .WithPath(new ExactMatcher("/type-conversion"))
        .UsingPost())
    .RespondWith(Response
        .Create()
        .WithHeader("Content-Type", "application/json")
        .WithBodyAsJson(new
        {
            timestamp = "{{ DateTime.UtcNow \"yyMMddhhmmss\" }}",
            timestamp_as_string = "{{ String.FormatAsString (DateTime.UtcNow) \"yyMMddhhmmss\" }}",
            timestamp_as_string_without_format = "{{ String.FormatAsString (DateTime.UtcNow) }}",

            random_number = "{{ Random Type='Integer' Min=1 Max=100 }}",
            random_number_as_number = "{{ Object.FormatAsObject (Random Type='Integer' Min=1 Max=100) }}",
            random_number_as_string = "{{ String.FormatAsString (Random Type='Integer' Min=1 Max=100) }}",

            number_from_body = "{{ request.bodyAsJson.number }}",
            number_from_body_as_number = "{{ Object.FormatAsObject (request.bodyAsJson.number) }}",
            number_from_body_as_string = "{{ String.FormatAsString (request.bodyAsJson.number) }}",

            numeric_string_from_body = "{{ request.bodyAsJson.numeric_string }}",
            numeric_string_from_body_as_number = "{{ Object.FormatAsObject (request.bodyAsJson.numeric_string) }}",
            numeric_string_from_body_as_string = "{{ String.FormatAsString (request.bodyAsJson.numeric_string) }}",
        })
        .WithTransformer(WireMock.Types.ReplaceNodeOptions.Evaluate));

HTTP Request/Response:

POST /type-conversion HTTP/1.1
Content-Type: application/json
 
{
  "number" : 999,
  "numeric_string": "011"
}
 
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 21 Dec 2023 18:14:42 GMT
 
{ 
  "timestamp":"231221061442",
  "timestamp_as_string":"231221061442",
  "timestamp_as_string_without_format":"21/12/2023 18:14:42",
  "random_number":"51",
  "random_number_as_number":"46",
  "random_number_as_string":"45",
  "number_from_body":999,
  "number_from_body_as_number":"999",
  "number_from_body_as_string":"999",
  "numeric_string_from_body":"011",
  "numeric_string_from_body_as_number":"011",
  "numeric_string_from_body_as_string":"011"
}

Results

  • String.FormatAsString looks good!

  • ⚠️ Object.FormatAsObject doesn't seem to work when used with ReplaceNodeOptions.Evaluate (check random_number_as_number, number_from_body_as_number, numeric_string_from_body_as_number).

I am not sure if I am missing something here... But I think the following unit test should be satisfied, right? Or do you want to deal with FormatAsNumber in another moment?

[Theory]
[InlineData(ReplaceNodeOptions.EvaluateAndTryToConvert)]
[InlineData(ReplaceNodeOptions.Evaluate)]
public async Task Response_WithBodyAsJson_ProvideResponseAsync_Handlebars_RandomIntegerWithObjectFormatAsNumber(ReplaceNodeOptions options)
{
    // Assign
    var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);

    var responseBuilder = Response.Create()
        .WithBodyAsJson(new
        {
            FormatAsNumber = "{{ Object.FormatAsObject (Random Type='Integer' Min=1 Max=100) }}"
        })
        .WithTransformer(options);

    // Act
    var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);

    // Assert
    var jObject = JObject.FromObject(response.Message.BodyData!.BodyAsJson!);
    jObject["FormatAsNumber"]!.Type.Should().Be(JTokenType.Integer);    
}

@felipetofoli commented on GitHub (Dec 21, 2023): > Can you try preview 1.5.43-ci-18158 ? @StefH I tried the preview package: ## Tests ### EvaluateAndTryToConvert (or default: `.WithTransformer()`) ```csharp server .Given(Request .Create() .WithPath(new ExactMatcher("/type-conversion")) .UsingPost()) .RespondWith(Response .Create() .WithHeader("Content-Type", "application/json") .WithBodyAsJson(new { timestamp = "{{ DateTime.UtcNow \"yyMMddhhmmss\" }}", timestamp_as_string = "{{ String.FormatAsString (DateTime.UtcNow) \"yyMMddhhmmss\" }}", timestamp_as_string_without_format = "{{ String.FormatAsString (DateTime.UtcNow) }}", random_number = "{{ Random Type='Integer' Min=1 Max=100 }}", random_number_as_number = "{{ Object.FormatAsObject (Random Type='Integer' Min=1 Max=100) }}", random_number_as_string = "{{ String.FormatAsString (Random Type='Integer' Min=1 Max=100) }}", number_from_body = "{{ request.bodyAsJson.number }}", number_from_body_as_number = "{{ Object.FormatAsObject (request.bodyAsJson.number) }}", number_from_body_as_string = "{{ String.FormatAsString (request.bodyAsJson.number) }}", numeric_string_from_body = "{{ request.bodyAsJson.numeric_string }}", numeric_string_from_body_as_number = "{{ Object.FormatAsObject (request.bodyAsJson.numeric_string) }}", numeric_string_from_body_as_string = "{{ String.FormatAsString (request.bodyAsJson.numeric_string) }}", }) .WithTransformer(WireMock.Types.ReplaceNodeOptions.EvaluateAndTryToConvert)); ``` HTTP Request/Response: ```http POST /type-conversion HTTP/1.1 Content-Type: application/json { "number" : 999, "numeric_string": "011" } HTTP/1.1 200 OK Content-Type: application/json Date: Thu, 21 Dec 2023 18:10:08 GMT { "timestamp":231221061008, "timestamp_as_string":"231221061008", "timestamp_as_string_without_format":"21/12/2023 18:10:08", "random_number":43, "random_number_as_number":8, "random_number_as_string":"2", "number_from_body":999, "number_from_body_as_number":999, "number_from_body_as_string":"999", "numeric_string_from_body":"011", "numeric_string_from_body_as_number":11, "numeric_string_from_body_as_string":"011" } ``` ### Evaluate ```csharp server .Given(Request .Create() .WithPath(new ExactMatcher("/type-conversion")) .UsingPost()) .RespondWith(Response .Create() .WithHeader("Content-Type", "application/json") .WithBodyAsJson(new { timestamp = "{{ DateTime.UtcNow \"yyMMddhhmmss\" }}", timestamp_as_string = "{{ String.FormatAsString (DateTime.UtcNow) \"yyMMddhhmmss\" }}", timestamp_as_string_without_format = "{{ String.FormatAsString (DateTime.UtcNow) }}", random_number = "{{ Random Type='Integer' Min=1 Max=100 }}", random_number_as_number = "{{ Object.FormatAsObject (Random Type='Integer' Min=1 Max=100) }}", random_number_as_string = "{{ String.FormatAsString (Random Type='Integer' Min=1 Max=100) }}", number_from_body = "{{ request.bodyAsJson.number }}", number_from_body_as_number = "{{ Object.FormatAsObject (request.bodyAsJson.number) }}", number_from_body_as_string = "{{ String.FormatAsString (request.bodyAsJson.number) }}", numeric_string_from_body = "{{ request.bodyAsJson.numeric_string }}", numeric_string_from_body_as_number = "{{ Object.FormatAsObject (request.bodyAsJson.numeric_string) }}", numeric_string_from_body_as_string = "{{ String.FormatAsString (request.bodyAsJson.numeric_string) }}", }) .WithTransformer(WireMock.Types.ReplaceNodeOptions.Evaluate)); ``` HTTP Request/Response: ```http POST /type-conversion HTTP/1.1 Content-Type: application/json { "number" : 999, "numeric_string": "011" } HTTP/1.1 200 OK Content-Type: application/json Date: Thu, 21 Dec 2023 18:14:42 GMT { "timestamp":"231221061442", "timestamp_as_string":"231221061442", "timestamp_as_string_without_format":"21/12/2023 18:14:42", "random_number":"51", "random_number_as_number":"46", "random_number_as_string":"45", "number_from_body":999, "number_from_body_as_number":"999", "number_from_body_as_string":"999", "numeric_string_from_body":"011", "numeric_string_from_body_as_number":"011", "numeric_string_from_body_as_string":"011" } ``` ## Results - ✅ `String.FormatAsString` looks good! - ⚠️ `Object.FormatAsObject` doesn't seem to work when used with `ReplaceNodeOptions.Evaluate` (check `random_number_as_number`, `number_from_body_as_number`, `numeric_string_from_body_as_number`). I am not sure if I am missing something here... But I think the following unit test should be satisfied, right? Or do you want to deal with `FormatAsNumber` in another moment? ```csharp [Theory] [InlineData(ReplaceNodeOptions.EvaluateAndTryToConvert)] [InlineData(ReplaceNodeOptions.Evaluate)] public async Task Response_WithBodyAsJson_ProvideResponseAsync_Handlebars_RandomIntegerWithObjectFormatAsNumber(ReplaceNodeOptions options) { // Assign var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp); var responseBuilder = Response.Create() .WithBodyAsJson(new { FormatAsNumber = "{{ Object.FormatAsObject (Random Type='Integer' Min=1 Max=100) }}" }) .WithTransformer(options); // Act var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); // Assert var jObject = JObject.FromObject(response.Message.BodyData!.BodyAsJson!); jObject["FormatAsNumber"]!.Type.Should().Be(JTokenType.Integer); } ```
Author
Owner

@StefH commented on GitHub (Dec 21, 2023):

FormatAsObject does indeed not work as expected.
However I need to think on that, probably will be fixed in future.

I'll merge the PR and create a new official NuGet.

@StefH commented on GitHub (Dec 21, 2023): FormatAsObject does indeed not work as expected. However I need to think on that, probably will be fixed in future. I'll merge the PR and create a new official NuGet.
Author
Owner

@felipetofoli commented on GitHub (Dec 21, 2023):

Thanks, @StefH !

@felipetofoli commented on GitHub (Dec 21, 2023): Thanks, @StefH !
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net-wiremock#486