diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Samples/ExampleMockValueBuilder.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Samples/ExampleMockValueBuilder.cs
new file mode 100644
index 00000000000..fd592a24e94
--- /dev/null
+++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Samples/ExampleMockValueBuilder.cs
@@ -0,0 +1,280 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.TypeSpec.Generator.Input;
+
+namespace Microsoft.TypeSpec.Generator.Samples
+{
+ ///
+ /// Generates mock instances for operations
+ /// that don't have examples provided in the spec.
+ ///
+ public static class ExampleMockValueBuilder
+ {
+ ///
+ /// Example key for the variant that includes only required parameters.
+ ///
+ public const string ShortVersionKey = "ShortVersion";
+
+ ///
+ /// Example key for the variant that includes all parameters.
+ ///
+ public const string AllParametersKey = "AllParameters";
+
+ private const string DefaultEndpointValue = "http://localhost:3000";
+
+ ///
+ /// Builds mock operation examples for the given operation.
+ /// Produces two variants: "ShortVersion" (required params only) and "AllParameters" (all params).
+ ///
+ public static IReadOnlyList BuildOperationExamples(InputOperation operation)
+ {
+ return new[]
+ {
+ BuildOperationExample(operation, ShortVersionKey, useAllParameters: false),
+ BuildOperationExample(operation, AllParametersKey, useAllParameters: true)
+ };
+ }
+
+ private static InputOperationExample BuildOperationExample(InputOperation operation, string name, bool useAllParameters)
+ {
+ var parameterExamples = new List(operation.Parameters.Count);
+ foreach (var parameter in operation.Parameters)
+ {
+ if (!useAllParameters && !parameter.IsRequired)
+ {
+ continue;
+ }
+ var parameterExample = BuildParameterExample(parameter, useAllParameters);
+ parameterExamples.Add(parameterExample);
+ }
+
+ return new InputOperationExample(name, null, parameterExamples, string.Empty);
+ }
+
+ ///
+ /// Builds a mock example value for a single parameter.
+ ///
+ internal static InputParameterExample BuildParameterExample(InputParameter parameter, bool useAllParameters)
+ {
+ // Constant parameters use their constant value directly
+ if (parameter.Scope == InputParameterScope.Constant)
+ {
+ var value = GetConstantValue(parameter);
+ return new InputParameterExample(parameter, value);
+ }
+
+ // Endpoint parameters use a mock URL
+ if (parameter is InputEndpointParameter { IsEndpoint: true })
+ {
+ var value = InputExampleValue.Value(parameter.Type, DefaultEndpointValue);
+ return new InputParameterExample(parameter, value);
+ }
+
+ // Parameters with default values use those
+ if (parameter.DefaultValue != null)
+ {
+ var value = InputExampleValue.Value(parameter.Type, parameter.DefaultValue.Value);
+ return new InputParameterExample(parameter, value);
+ }
+
+ // Everything else: generate a mock value based on the type
+ var exampleValue = BuildExampleValue(parameter.Type, parameter.Name, useAllParameters, new HashSet());
+ return new InputParameterExample(parameter, exampleValue);
+ }
+
+ private static InputExampleValue GetConstantValue(InputParameter parameter)
+ {
+ if (parameter.Type is InputLiteralType { Value: not null } literal)
+ {
+ return InputExampleValue.Value(parameter.Type, literal.Value);
+ }
+ if (parameter.DefaultValue != null)
+ {
+ return InputExampleValue.Value(parameter.Type, parameter.DefaultValue.Value);
+ }
+ if (parameter.Type is InputUnionType unionType && unionType.VariantTypes[0] is InputLiteralType literalVariant)
+ {
+ return InputExampleValue.Value(parameter.Type, literalVariant.Value);
+ }
+ if (parameter.Type is InputEnumType enumType && enumType.Values.Count > 0)
+ {
+ return InputExampleValue.Value(parameter.Type, enumType.Values[0].Value);
+ }
+ return InputExampleValue.Null(parameter.Type);
+ }
+
+ ///
+ /// Builds a mock example value for the given input type.
+ /// This is the main dispatch method that handles all type kinds.
+ ///
+ internal static InputExampleValue BuildExampleValue(InputType type, string? hint, bool useAllParameters, HashSet visitedModels) => type switch
+ {
+ InputArrayType arrayType => BuildListExampleValue(arrayType, hint, useAllParameters, visitedModels),
+ InputDictionaryType dictType => BuildDictionaryExampleValue(dictType, hint, useAllParameters, visitedModels),
+ InputEnumType enumType => BuildEnumExampleValue(enumType),
+ InputPrimitiveType primitiveType => BuildPrimitiveExampleValue(primitiveType, hint),
+ InputLiteralType literalType => InputExampleValue.Value(literalType, literalType.Value),
+ InputModelType modelType => BuildModelExampleValue(modelType, useAllParameters, visitedModels),
+ InputUnionType unionType => BuildExampleValue(unionType.VariantTypes[0], hint, useAllParameters, visitedModels),
+ InputNullableType nullableType => BuildExampleValue(nullableType.Type, hint, useAllParameters, visitedModels),
+ InputDateTimeType dateTimeType => BuildDateTimeExampleValue(dateTimeType),
+ InputDurationType durationType => BuildDurationExampleValue(durationType),
+ _ => InputExampleValue.Object(type, new Dictionary())
+ };
+
+ private static InputExampleValue BuildListExampleValue(InputArrayType arrayType, string? hint, bool useAllParameters, HashSet visitedModels)
+ {
+ var elementValue = BuildExampleValue(arrayType.ValueType, hint, useAllParameters, visitedModels);
+ return InputExampleValue.List(arrayType, new[] { elementValue });
+ }
+
+ private static InputExampleValue BuildDictionaryExampleValue(InputDictionaryType dictType, string? hint, bool useAllParameters, HashSet visitedModels)
+ {
+ var valueExample = BuildExampleValue(dictType.ValueType, hint, useAllParameters, visitedModels);
+ return InputExampleValue.Object(dictType, new Dictionary
+ {
+ ["key"] = valueExample
+ });
+ }
+
+ private static InputExampleValue BuildEnumExampleValue(InputEnumType enumType)
+ {
+ var firstValue = enumType.Values.FirstOrDefault();
+ return firstValue != null
+ ? InputExampleValue.Value(enumType, firstValue.Value)
+ : InputExampleValue.Null(enumType);
+ }
+
+ private static InputExampleValue BuildPrimitiveExampleValue(InputPrimitiveType primitiveType, string? hint) => primitiveType.Kind switch
+ {
+ InputPrimitiveTypeKind.Boolean => InputExampleValue.Value(primitiveType, true),
+ InputPrimitiveTypeKind.Int8 => InputExampleValue.Value(primitiveType, (sbyte)123),
+ InputPrimitiveTypeKind.UInt8 => InputExampleValue.Value(primitiveType, (byte)123),
+ InputPrimitiveTypeKind.Int16 => InputExampleValue.Value(primitiveType, (short)1234),
+ InputPrimitiveTypeKind.Int32 or InputPrimitiveTypeKind.Integer => InputExampleValue.Value(primitiveType, 1234),
+ InputPrimitiveTypeKind.Int64 or InputPrimitiveTypeKind.SafeInt => InputExampleValue.Value(primitiveType, 1234L),
+ InputPrimitiveTypeKind.UInt16 => InputExampleValue.Value(primitiveType, (ushort)1234),
+ InputPrimitiveTypeKind.UInt32 => InputExampleValue.Value(primitiveType, (uint)1234),
+ InputPrimitiveTypeKind.UInt64 => InputExampleValue.Value(primitiveType, (ulong)1234),
+ InputPrimitiveTypeKind.Float32 or InputPrimitiveTypeKind.Float => InputExampleValue.Value(primitiveType, 123.45f),
+ InputPrimitiveTypeKind.Float64 or InputPrimitiveTypeKind.Numeric => InputExampleValue.Value(primitiveType, 123.45),
+ InputPrimitiveTypeKind.Decimal or InputPrimitiveTypeKind.Decimal128 => InputExampleValue.Value(primitiveType, 123.45m),
+ InputPrimitiveTypeKind.String => BuildStringExampleValue(primitiveType, hint),
+ InputPrimitiveTypeKind.Url => InputExampleValue.Value(primitiveType, "http://localhost:3000"),
+ InputPrimitiveTypeKind.PlainDate => InputExampleValue.Value(primitiveType, "2022-05-10"),
+ InputPrimitiveTypeKind.PlainTime => InputExampleValue.Value(primitiveType, "01:23:45"),
+ InputPrimitiveTypeKind.Stream => InputExampleValue.Stream(primitiveType, ""),
+ InputPrimitiveTypeKind.Bytes => InputExampleValue.Value(primitiveType, "dGVzdA=="), // base64 for "test"
+ _ => InputExampleValue.Object(primitiveType, new Dictionary())
+ };
+
+ private static InputExampleValue BuildStringExampleValue(InputPrimitiveType primitiveType, string? hint)
+ {
+ // UUID-typed strings get a mock UUID
+ if (primitiveType.Encode == "uuid")
+ {
+ return InputExampleValue.Value(primitiveType, "73f411fe-4f43-4b4b-9cbd-6828d8f4cf9a");
+ }
+
+ return string.IsNullOrWhiteSpace(hint)
+ ? InputExampleValue.Value(primitiveType, "")
+ : InputExampleValue.Value(primitiveType, $"<{hint}>");
+ }
+
+ private static InputExampleValue BuildDateTimeExampleValue(InputDateTimeType dateTimeType)
+ {
+ if (dateTimeType.Encode == DateTimeKnownEncoding.Rfc7231)
+ return InputExampleValue.Value(dateTimeType.WireType, "Tue, 10 May 2022 18:57:31 GMT");
+ if (dateTimeType.Encode == DateTimeKnownEncoding.Rfc3339)
+ return InputExampleValue.Value(dateTimeType.WireType, "2022-05-10T18:57:31.2311892Z");
+ if (dateTimeType.Encode == DateTimeKnownEncoding.UnixTimestamp)
+ return InputExampleValue.Value(dateTimeType.WireType, 1652209051);
+
+ return InputExampleValue.Null(dateTimeType);
+ }
+
+ private static InputExampleValue BuildDurationExampleValue(InputDurationType durationType)
+ {
+ if (durationType.Encode == DurationKnownEncoding.Iso8601)
+ return InputExampleValue.Value(durationType.WireType, "PT1H23M45S");
+
+ if (durationType.Encode == DurationKnownEncoding.Seconds)
+ {
+ return durationType.WireType.Kind switch
+ {
+ InputPrimitiveTypeKind.Int32 => InputExampleValue.Value(durationType.WireType, 10),
+ InputPrimitiveTypeKind.Float or InputPrimitiveTypeKind.Float32 => InputExampleValue.Value(durationType.WireType, 10f),
+ _ => InputExampleValue.Value(durationType.WireType, 3.141592)
+ };
+ }
+
+ return InputExampleValue.Null(durationType);
+ }
+
+ private static InputExampleValue BuildModelExampleValue(InputModelType model, bool useAllParameters, HashSet visitedModels)
+ {
+ // Cycle detection: if we've already visited this model, return null to break the loop
+ if (visitedModels.Contains(model))
+ return InputExampleValue.Null(model);
+
+ var properties = new Dictionary();
+ var result = InputExampleValue.Object(model, properties);
+ visitedModels.Add(model);
+
+ // If this model has a discriminator, choose the first derived type
+ if (model.DiscriminatorProperty != null && model.DerivedModels.Count > 0)
+ {
+ var derived = model.DerivedModels.FirstOrDefault(m => !m.IsUnknownDiscriminatorModel);
+ if (derived != null)
+ {
+ model = derived;
+ }
+ else
+ {
+ return InputExampleValue.Null(model);
+ }
+ }
+
+ // Iterate all properties from this model and its base models
+ foreach (var modelInChain in model.GetSelfAndBaseModels())
+ {
+ foreach (var property in modelInChain.Properties)
+ {
+ // Skip read-only properties (they can't be set)
+ if (property.IsReadOnly)
+ continue;
+
+ // In ShortVersion, skip optional properties
+ if (!useAllParameters && !property.IsRequired)
+ continue;
+
+ // Skip duplicate properties (keep the one from the most-derived type)
+ if (properties.ContainsKey(property.SerializedName))
+ continue;
+
+ InputExampleValue exampleValue;
+ if (property.IsDiscriminator && model.DiscriminatorValue != null)
+ {
+ exampleValue = InputExampleValue.Value(property.Type, model.DiscriminatorValue);
+ }
+ else if (property.DefaultValue is { Value: not null } defaultValue)
+ {
+ exampleValue = InputExampleValue.Value(property.Type, defaultValue.Value);
+ }
+ else
+ {
+ exampleValue = BuildExampleValue(property.Type, property.SerializedName, useAllParameters, visitedModels);
+ }
+
+ properties.Add(property.SerializedName, exampleValue);
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Samples/ExampleMockValueBuilderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Samples/ExampleMockValueBuilderTests.cs
new file mode 100644
index 00000000000..232067ce99d
--- /dev/null
+++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Samples/ExampleMockValueBuilderTests.cs
@@ -0,0 +1,536 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Microsoft.TypeSpec.Generator.Input;
+using Microsoft.TypeSpec.Generator.Samples;
+using Microsoft.TypeSpec.Generator.Tests.Common;
+using NUnit.Framework;
+
+namespace Microsoft.TypeSpec.Generator.Tests.Samples
+{
+ public class ExampleMockValueBuilderTests
+ {
+ // -----------------------------------------------------------------------
+ // BuildOperationExamples — top-level behavior
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void BuildOperationExamples_ProducesTwoVariants()
+ {
+ var operation = InputFactory.Operation("TestOp", parameters: [
+ InputFactory.PathParameter("id", InputPrimitiveType.String, isRequired: true)
+ ]);
+
+ var examples = ExampleMockValueBuilder.BuildOperationExamples(operation);
+
+ Assert.AreEqual(2, examples.Count);
+ Assert.AreEqual(ExampleMockValueBuilder.ShortVersionKey, examples[0].Name);
+ Assert.AreEqual(ExampleMockValueBuilder.AllParametersKey, examples[1].Name);
+ }
+
+ [Test]
+ public void ShortVersion_SkipsOptionalParameters()
+ {
+ var operation = InputFactory.Operation("TestOp", parameters: [
+ InputFactory.PathParameter("requiredId", InputPrimitiveType.String, isRequired: true),
+ InputFactory.QueryParameter("optionalFilter", InputPrimitiveType.String, isRequired: false)
+ ]);
+
+ var examples = ExampleMockValueBuilder.BuildOperationExamples(operation);
+ var shortVersion = examples[0];
+ var allParams = examples[1];
+
+ Assert.AreEqual(1, shortVersion.Parameters.Count);
+ Assert.AreEqual("requiredId", shortVersion.Parameters[0].Parameter.Name);
+
+ Assert.AreEqual(2, allParams.Parameters.Count);
+ }
+
+ [Test]
+ public void AllParameters_IncludesOptionalParameters()
+ {
+ var operation = InputFactory.Operation("TestOp", parameters: [
+ InputFactory.PathParameter("requiredId", InputPrimitiveType.String, isRequired: true),
+ InputFactory.QueryParameter("optionalFilter", InputPrimitiveType.String, isRequired: false),
+ InputFactory.HeaderParameter("optionalHeader", InputPrimitiveType.Int32, isRequired: false)
+ ]);
+
+ var examples = ExampleMockValueBuilder.BuildOperationExamples(operation);
+ var allParams = examples[1];
+
+ Assert.AreEqual(3, allParams.Parameters.Count);
+ }
+
+ [Test]
+ public void EmptyFilePath_ForMockExamples()
+ {
+ var operation = InputFactory.Operation("TestOp", parameters: [
+ InputFactory.PathParameter("id", InputPrimitiveType.String, isRequired: true)
+ ]);
+
+ var examples = ExampleMockValueBuilder.BuildOperationExamples(operation);
+
+ Assert.AreEqual(string.Empty, examples[0].FilePath);
+ Assert.AreEqual(string.Empty, examples[1].FilePath);
+ }
+
+ // -----------------------------------------------------------------------
+ // Primitive type mock values
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void PrimitiveType_Boolean()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.Boolean);
+ AssertRawValue(value, true);
+ }
+
+ [Test]
+ public void PrimitiveType_Int32()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.Int32);
+ AssertRawValue(value, 1234);
+ }
+
+ [Test]
+ public void PrimitiveType_Int64()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.Int64);
+ AssertRawValue(value, 1234L);
+ }
+
+ [Test]
+ public void PrimitiveType_Float32()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.Float32);
+ AssertRawValue(value, 123.45f);
+ }
+
+ [Test]
+ public void PrimitiveType_Float64()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.Float64);
+ AssertRawValue(value, 123.45);
+ }
+
+ [Test]
+ public void PrimitiveType_String_WithHint()
+ {
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ InputPrimitiveType.String, "myParam", false, new HashSet());
+
+ AssertRawValue(value, "");
+ }
+
+ [Test]
+ public void PrimitiveType_String_WithoutHint()
+ {
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ InputPrimitiveType.String, null, false, new HashSet());
+
+ AssertRawValue(value, "");
+ }
+
+ [Test]
+ public void PrimitiveType_Url()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.Url);
+ AssertRawValue(value, "http://localhost:3000");
+ }
+
+ [Test]
+ public void PrimitiveType_PlainDate()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.PlainDate);
+ AssertRawValue(value, "2022-05-10");
+ }
+
+ [Test]
+ public void PrimitiveType_PlainTime()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.PlainTime);
+ AssertRawValue(value, "01:23:45");
+ }
+
+ [Test]
+ public void PrimitiveType_Bytes()
+ {
+ var value = BuildExampleValueForType(InputPrimitiveType.Base64);
+ AssertRawValue(value, "dGVzdA==");
+ }
+
+ [Test]
+ public void PrimitiveType_Uuid_String()
+ {
+ var uuidType = new InputPrimitiveType(InputPrimitiveTypeKind.String, "string", "TypeSpec.string", "uuid");
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ uuidType, "id", false, new HashSet());
+
+ AssertRawValue(value, "73f411fe-4f43-4b4b-9cbd-6828d8f4cf9a");
+ }
+
+ // -----------------------------------------------------------------------
+ // DateTime mock values
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void DateTime_Rfc3339()
+ {
+ var dateTimeType = new InputDateTimeType(
+ DateTimeKnownEncoding.Rfc3339, "dateTime", "TypeSpec.utcDateTime", InputPrimitiveType.String);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ dateTimeType, null, false, new HashSet());
+
+ AssertRawValue(value, "2022-05-10T18:57:31.2311892Z");
+ }
+
+ [Test]
+ public void DateTime_Rfc7231()
+ {
+ var dateTimeType = new InputDateTimeType(
+ DateTimeKnownEncoding.Rfc7231, "dateTime", "TypeSpec.utcDateTime", InputPrimitiveType.String);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ dateTimeType, null, false, new HashSet());
+
+ AssertRawValue(value, "Tue, 10 May 2022 18:57:31 GMT");
+ }
+
+ [Test]
+ public void DateTime_UnixTimestamp()
+ {
+ var dateTimeType = new InputDateTimeType(
+ DateTimeKnownEncoding.UnixTimestamp, "dateTime", "TypeSpec.utcDateTime", InputPrimitiveType.Int64);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ dateTimeType, null, false, new HashSet());
+
+ AssertRawValue(value, 1652209051);
+ }
+
+ // -----------------------------------------------------------------------
+ // Duration mock values
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void Duration_Iso8601()
+ {
+ var durationType = new InputDurationType(
+ DurationKnownEncoding.Iso8601, "duration", "TypeSpec.duration", InputPrimitiveType.String, null);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ durationType, null, false, new HashSet());
+
+ AssertRawValue(value, "PT1H23M45S");
+ }
+
+ [Test]
+ public void Duration_Seconds_Int32()
+ {
+ var durationType = new InputDurationType(
+ DurationKnownEncoding.Seconds, "duration", "TypeSpec.duration", InputPrimitiveType.Int32, null);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ durationType, null, false, new HashSet());
+
+ AssertRawValue(value, 10);
+ }
+
+ // -----------------------------------------------------------------------
+ // Collection mock values
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void Array_ProducesSingleElementList()
+ {
+ var arrayType = new InputArrayType("list", "TypeSpec.Array", InputPrimitiveType.Int32);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ arrayType, null, false, new HashSet());
+
+ // The value should be a list type — verify via the Type property
+ Assert.AreEqual(arrayType, value.Type);
+ // We can't access internal Values directly, but we can verify it's not null/raw
+ AssertIsNotRawNull(value);
+ }
+
+ [Test]
+ public void Dictionary_ProducesSingleKeyEntry()
+ {
+ var dictType = new InputDictionaryType("dict", InputPrimitiveType.String, InputPrimitiveType.Int32);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ dictType, null, false, new HashSet());
+
+ Assert.AreEqual(dictType, value.Type);
+ AssertIsNotRawNull(value);
+ }
+
+ // -----------------------------------------------------------------------
+ // Enum mock values
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void Enum_ReturnsFirstEnumValue()
+ {
+ var enumType = InputFactory.StringEnum("Color", [("Red", "red"), ("Blue", "blue")]);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ enumType, null, false, new HashSet());
+
+ AssertRawValue(value, "red");
+ }
+
+ [Test]
+ public void Enum_Int32_ReturnsFirstValue()
+ {
+ var enumType = InputFactory.Int32Enum("Status", [("Active", 1), ("Inactive", 0)]);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ enumType, null, false, new HashSet());
+
+ AssertRawValue(value, 1);
+ }
+
+ // -----------------------------------------------------------------------
+ // Literal type
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void LiteralType_ReturnsLiteralValue()
+ {
+ var literalType = InputFactory.Literal.String("fixedValue");
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ literalType, null, false, new HashSet());
+
+ AssertRawValue(value, "fixedValue");
+ }
+
+ // -----------------------------------------------------------------------
+ // Union type
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void UnionType_ReturnsFirstVariant()
+ {
+ var unionType = new InputUnionType("myUnion", [InputPrimitiveType.String, InputPrimitiveType.Int32]);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ unionType, "field", false, new HashSet());
+
+ // Should pick the first variant (String) and mock it
+ AssertRawValue(value, "");
+ }
+
+ // -----------------------------------------------------------------------
+ // Nullable type
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void NullableType_UnwrapsAndMocksInner()
+ {
+ var nullableType = new InputNullableType(InputPrimitiveType.Int32);
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ nullableType, null, false, new HashSet());
+
+ AssertRawValue(value, 1234);
+ }
+
+ // -----------------------------------------------------------------------
+ // Model mock values
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void Model_PopulatesRequiredProperties()
+ {
+ var model = InputFactory.Model("Widget", properties: [
+ InputFactory.Property("name", InputPrimitiveType.String, isRequired: true),
+ InputFactory.Property("optionalColor", InputPrimitiveType.String, isRequired: false)
+ ]);
+
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ model, null, false, new HashSet());
+
+ // Should be an object value (not null/raw)
+ Assert.AreEqual(model, value.Type);
+ AssertIsNotRawNull(value);
+ }
+
+ [Test]
+ public void Model_PopulatesAllProperties_WhenUseAll()
+ {
+ var model = InputFactory.Model("Widget", properties: [
+ InputFactory.Property("name", InputPrimitiveType.String, isRequired: true),
+ InputFactory.Property("optionalColor", InputPrimitiveType.String, isRequired: false)
+ ]);
+
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ model, null, true, new HashSet());
+
+ Assert.AreEqual(model, value.Type);
+ AssertIsNotRawNull(value);
+ }
+
+ [Test]
+ public void Model_SkipsReadOnlyProperties()
+ {
+ var model = InputFactory.Model("Widget", properties: [
+ InputFactory.Property("name", InputPrimitiveType.String, isRequired: true),
+ InputFactory.Property("id", InputPrimitiveType.String, isRequired: true, isReadOnly: true)
+ ]);
+
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ model, null, true, new HashSet());
+
+ Assert.AreEqual(model, value.Type);
+ AssertIsNotRawNull(value);
+ }
+
+ [Test]
+ public void Model_IncludesBaseModelProperties()
+ {
+ var baseModel = InputFactory.Model("BaseWidget", properties: [
+ InputFactory.Property("baseField", InputPrimitiveType.String, isRequired: true)
+ ]);
+ var derivedModel = InputFactory.Model("DerivedWidget", baseModel: baseModel, properties: [
+ InputFactory.Property("derivedField", InputPrimitiveType.Int32, isRequired: true)
+ ]);
+
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ derivedModel, null, true, new HashSet());
+
+ AssertIsNotRawNull(value);
+ }
+
+ [Test]
+ public void Model_CircularReference_ReturnsNull()
+ {
+ var selfRefModel = InputFactory.Model("Node", properties: [
+ InputFactory.Property("name", InputPrimitiveType.String, isRequired: true)
+ ]);
+
+ // Pre-add to visited set to simulate circular reference
+ var visited = new HashSet { selfRefModel };
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ selfRefModel, null, true, visited);
+
+ // Circular reference should produce a null value
+ Assert.IsNotNull(value);
+ Assert.AreEqual(selfRefModel, value.Type);
+ }
+
+ [Test]
+ public void Model_WithDiscriminator_ChoosesDerivedType()
+ {
+ var baseModel = InputFactory.Model("Pet",
+ properties: [
+ InputFactory.Property("kind", InputPrimitiveType.String, isRequired: true, isDiscriminator: true)
+ ],
+ discriminatedModels: new Dictionary());
+
+ var catModel = InputFactory.Model("Cat",
+ discriminatedKind: "cat",
+ baseModel: baseModel,
+ properties: [
+ InputFactory.Property("meow", InputPrimitiveType.Boolean, isRequired: true)
+ ]);
+
+ var value = ExampleMockValueBuilder.BuildExampleValue(
+ baseModel, null, true, new HashSet());
+
+ // Should produce a non-null object value (derived type selected)
+ Assert.IsNotNull(value);
+ AssertIsNotRawNull(value);
+ }
+
+ // -----------------------------------------------------------------------
+ // Parameter handling
+ // -----------------------------------------------------------------------
+
+ [Test]
+ public void Parameter_Endpoint_UsesMockUrl()
+ {
+ var endpointParam = InputFactory.EndpointParameter("endpoint", InputPrimitiveType.Url, isRequired: true);
+ var operation = InputFactory.Operation("TestOp", parameters: [endpointParam]);
+
+ var examples = ExampleMockValueBuilder.BuildOperationExamples(operation);
+ var paramExample = examples[0].Parameters[0];
+
+ AssertRawValue(paramExample.ExampleValue, "http://localhost:3000");
+ }
+
+ [Test]
+ public void Parameter_Constant_UsesConstantValue()
+ {
+ var constParam = InputFactory.HeaderParameter("apiVersion", InputFactory.Literal.String("2024-01-01"),
+ isRequired: true, scope: InputParameterScope.Constant,
+ defaultValue: InputFactory.Constant.String("2024-01-01"));
+
+ var operation = InputFactory.Operation("TestOp", parameters: [constParam]);
+
+ var examples = ExampleMockValueBuilder.BuildOperationExamples(operation);
+ var paramExample = examples[0].Parameters[0];
+
+ AssertRawValue(paramExample.ExampleValue, "2024-01-01");
+ }
+
+ [Test]
+ public void Parameter_WithDefaultValue_UsesDefault()
+ {
+ var paramWithDefault = InputFactory.QueryParameter("count", InputPrimitiveType.Int32,
+ isRequired: true, defaultValue: new InputConstant(10, InputPrimitiveType.Int32));
+
+ var operation = InputFactory.Operation("TestOp", parameters: [paramWithDefault]);
+
+ var examples = ExampleMockValueBuilder.BuildOperationExamples(operation);
+ var paramExample = examples[0].Parameters[0];
+
+ AssertRawValue(paramExample.ExampleValue, 10);
+ }
+
+ [Test]
+ public void OperationWithNoParameters_ProducesEmptyExamples()
+ {
+ var operation = InputFactory.Operation("EmptyOp", parameters: []);
+
+ var examples = ExampleMockValueBuilder.BuildOperationExamples(operation);
+
+ Assert.AreEqual(2, examples.Count);
+ Assert.AreEqual(0, examples[0].Parameters.Count);
+ Assert.AreEqual(0, examples[1].Parameters.Count);
+ }
+
+ // -----------------------------------------------------------------------
+ // Helpers
+ // -----------------------------------------------------------------------
+
+ private static InputExampleValue BuildExampleValueForType(InputType type)
+ {
+ return ExampleMockValueBuilder.BuildExampleValue(type, null, false, new HashSet());
+ }
+
+ ///
+ /// Asserts that the value is a raw example value matching the expected object.
+ /// Since InputExampleRawValue is internal, we use reflection to access RawValue.
+ ///
+ private static void AssertRawValue(InputExampleValue value, object expected)
+ {
+ var expectedValue = InputExampleValue.Value(value.Type, expected);
+ Assert.AreEqual(expectedValue.GetType(), value.GetType(),
+ $"Expected raw value type but got {value.GetType().Name}");
+ var rawValueProp = value.GetType().GetProperty("RawValue");
+ Assert.IsNotNull(rawValueProp, "Expected value to have RawValue property");
+ var actualRaw = rawValueProp!.GetValue(value);
+ Assert.AreEqual(expected, actualRaw);
+ }
+
+ ///
+ /// Asserts the value is not a null raw value — it should be a composite type (list, object).
+ ///
+ private static void AssertIsNotRawNull(InputExampleValue value)
+ {
+ var rawValueProp = value.GetType().GetProperty("RawValue");
+ if (rawValueProp != null)
+ {
+ // It's a raw value — it should not be null (meaning it was a real value, not a cycle)
+ var rawVal = rawValueProp.GetValue(value);
+ Assert.IsNotNull(rawVal, "Expected a non-null value but got null (possible circular reference issue)");
+ }
+ // If no RawValue property, it's a list/object/stream — that's fine
+ }
+ }
+}