# Dotnet Testing Autodata Xunit Integration

> Complete guide for AutoFixture and xUnit integration. Use when you need to use AutoData or InlineAutoData to simplify xUnit parameterized test data preparation. Covers custom Customization and test data attributes to improve test readability and maintainability. Keywords: AutoData, InlineAutoData, AutoFixture xUnit, [AutoData], [InlineAutoData], AutoDataAttribute, ICustomization, DataAttribute, parameterized test, Theory AutoData, MemberAutoData, test data attributes, fixture.Customize

- Skill: `rudironsoni/dotnet-testing-autodata-xunit-integration-4` (Agent Skill)
- Install (CLI): `npx skillmds@latest add rudironsoni/dotnet-testing-autodata-xunit-integration-4`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rudironsoni/dotnet-testing-autodata-xunit-integration-4/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- License: MIT
- Author: rudironsoni (https://skillmd.com/u/rudironsoni)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/rudironsoni/dotnet-testing-autodata-xunit-integration-4

---


Source: kevintsengtw/dotnet-testing-agent-skills (MIT). Ported into dotnet-agent-harness.

# AutoData Attribute Family: xUnit and AutoFixture Integration Application

## Applicable Scenarios

- AutoData
- InlineAutoData
- MemberAutoData
- CompositeAutoData
- xUnit AutoFixture integration
- parameterized test data
- test parameter injection
- CollectionSizeAttribute
- external test data
- CSV test data
- JSON test data

## Overview

The AutoData attribute family is a feature provided by the `AutoFixture.Xunit2` package, integrating AutoFixture's data
generation capabilities with xUnit's parameterized tests, allowing test parameters to be automatically injected,
significantly reducing test preparation code.

### Core Features

1. **AutoData**: Automatically generate all test parameters
2. **InlineAutoData**: Mix fixed values with auto-generation
3. **MemberAutoData**: Combine external data sources
4. **CompositeAutoData**: Multiple data source integration
5. **CollectionSizeAttribute**: Control collection generation quantity

## Package Installation

````xml
<PackageReference Include="AutoFixture" Version="4.18.1" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.1" />
```text

```bash
dotnet add package AutoFixture.Xunit2
```text

## AutoData: Fully Automatic Parameter Generation

`AutoData` is the most basic attribute, automatically generating test data for all parameters of a test method.

### Basic Usage

```csharp
using AutoFixture.Xunit2;

public class Person
{
    public Guid Id { get; set; }

    [StringLength(10)]
    public string Name { get; set; } = string.Empty;

    [Range(18, 80)]
    public int Age { get; set; }

    public string Email { get; set; } = string.Empty;
    public DateTime CreateTime { get; set; }
}

[Theory]
[AutoData]
public void AutoData_Should_Automatically_Generate_All_Parameters(Person person, string message, int count)
{
    // Arrange & Act - Parameters automatically generated by AutoData

    // Assert
    person.Should().NotBeNull();
    person.Id.Should().NotBe(Guid.Empty);
    person.Name.Should().HaveLength(10);     // Follows StringLength constraint
    person.Age.Should().BeInRange(18, 80);   // Follows Range constraint
    message.Should().NotBeNullOrEmpty();
    count.Should().NotBe(0);
}
```text

### Constrain Parameters via DataAnnotation

```csharp
[Theory]
[AutoData]
public void AutoData_Constrain_Parameters_Via_DataAnnotation(
    [StringLength(5, MinimumLength = 3)] string shortName,
    [Range(1, 100)] int percentage,
    Person person)
{
    // Assert
    shortName.Length.Should().BeInRange(3, 5);
    percentage.Should().BeInRange(1, 100);
    person.Should().NotBeNull();
}
```text

## InlineAutoData: Mixing Fixed Values with Auto-Generation

`InlineAutoData` combines the fixed value characteristic of `InlineData` with the auto-generation functionality of `AutoData`.

### Basic Syntax

```csharp
[Theory]
[InlineAutoData("VIP Customer", 1000)]
[InlineAutoData("Regular Customer", 500)]
[InlineAutoData("New Customer", 100)]
public void InlineAutoData_Mix_Fixed_Values_With_Auto_Generate(
    string customerType,    // Corresponds to 1st fixed value
    decimal creditLimit,    // Corresponds to 2nd fixed value
    Person person)          // Generated by AutoFixture
{
    // Arrange
    var customer = new Customer
    {
        Person = person,
        Type = customerType,
        CreditLimit = creditLimit
    };

    // Assert
    customer.Type.Should().Be(customerType);
    customer.CreditLimit.Should().BeOneOf(1000, 500, 100);
    customer.Person.Should().NotBeNull();
}
```text

### Parameter Order Consistency

Fixed value order must match method parameter order:

```csharp
[Theory]
[InlineAutoData("Product A", 100)]  // Sequentially correspond to name, price
[InlineAutoData("Product B", 200)]
public void InlineAutoData_Parameter_Order_Consistency(
    string name,        // Corresponds to 1st fixed value
    decimal price,      // Corresponds to 2nd fixed value
    string description, // Generated by AutoFixture
    Product product)    // Generated by AutoFixture
{
    // Assert
    name.Should().BeOneOf("Product A", "Product B");
    price.Should().BeOneOf(100, 200);
    description.Should().NotBeNullOrEmpty();
    product.Should().NotBeNull();
}
```text

### ⚠️ Important Limitation: Only Compile-Time Constants

```csharp
// ✅ Correct: Use constants
[InlineAutoData("VIP", 100000)]
[InlineAutoData("Premium", 50000)]

// ❌ Wrong: Cannot use variables
private const decimal VipCreditLimit = 100000m;
[InlineAutoData("VIP", VipCreditLimit)]  // Compile error

// ❌ Wrong: Cannot use expressions
[InlineAutoData("VIP", 100 * 1000)]  // Compile error
```text

When complex data is needed, use `MemberAutoData` instead.

## MemberAutoData: Combining External Data Sources

`MemberAutoData` allows obtaining test data from class methods, properties, or fields.

### Using Static Methods

```csharp
public class MemberAutoDataTests
{
    public static IEnumerable<object[]> GetProductCategories()
    {
        yield return new object[] { "3C Products", "TECH" };
        yield return new object[] { "Clothing & Accessories", "FASHION" };
        yield return new object[] { "Home & Living", "HOME" };
        yield return new object[] { "Sports & Fitness", "SPORTS" };
    }

    [Theory]
    [MemberAutoData(nameof(GetProductCategories))]
    public void MemberAutoData_Using_Static_Method_Data(
        string categoryName,   // From GetProductCategories
        string categoryCode,   // From GetProductCategories
        Product product)       // Generated by AutoFixture
    {
        // Arrange
        var categorizedProduct = new CategorizedProduct
        {
            Product = product,
            CategoryName = categoryName,
            CategoryCode = categoryCode
        };

        // Assert
        categorizedProduct.CategoryName.Should().Be(categoryName);
        categorizedProduct.CategoryCode.Should().Be(categoryCode);
        categorizedProduct.Product.Should().NotBeNull();
    }
}
```text

### Using Static Properties

```csharp
public static IEnumerable<object[]> StatusTransitions => new[]
{
    new object[] { OrderStatus.Created, OrderStatus.Confirmed },
    new object[] { OrderStatus.Confirmed, OrderStatus.Shipped },
    new object[] { OrderStatus.Shipped, OrderStatus.Delivered },
    new object[] { OrderStatus.Delivered, OrderStatus.Completed }
};

[Theory]
[MemberAutoData(nameof(StatusTransitions))]
public void MemberAutoData_Using_Static_Property_Order_Status_Transition(
    OrderStatus fromStatus,
    OrderStatus toStatus,
    Order order)
{
    // Arrange
    order.Status = fromStatus;

    // Act
    order.TransitionTo(toStatus);

    // Assert
    order.Status.Should().Be(toStatus);
}
```text

## Custom AutoData Attributes

Create dedicated AutoData configurations:

### DomainAutoDataAttribute

```csharp
public class DomainAutoDataAttribute : AutoDataAttribute
{
    public DomainAutoDataAttribute() : base(() => CreateFixture())
    {
    }

    private static IFixture CreateFixture()
    {
        var fixture = new Fixture();

        // Set custom rules for Person
        fixture.Customize<Person>(composer => composer
            .With(p => p.Age, () => Random.Shared.Next(18, 65))
            .With(p => p.Email, () => $"user{Random.Shared.Next(1000)}@example.com")
            .With(p => p.Name, () => $"Test User{Random.Shared.Next(100)}"));

        // Set custom rules for Product
        fixture.Customize<Product>(composer => composer
            .With(p => p.Price, () => Random.Shared.Next(100, 10000))
            .With(p => p.IsAvailable, true)
            .With(p => p.Name, () => $"Product{Random.Shared.Next(1000)}"));

        return fixture;
    }
}
```text

### BusinessAutoDataAttribute

```csharp
public class BusinessAutoDataAttribute : AutoDataAttribute
{
    public BusinessAutoDataAttribute() : base(() => CreateFixture())
    {
    }

    private static IFixture CreateFixture()
    {
        var fixture = new Fixture();

        // Set business rules for Order
        fixture.Customize<Order>(composer => composer
            .With(o => o.Status, OrderStatus.Created)
            .With(o => o.Amount, () => Random.Shared.Next(1000, 50000))
            .With(o => o.OrderNumber, () => $"ORD{DateTime.Now:yyyyMMdd}{Random.Shared.Next(1000):D4}"));

        return fixture;
    }
}
```text

### Using Custom AutoData

```csharp
[Theory]
[DomainAutoData]
public void Using_DomainAutoData(Person person, Product product)
{
    person.Age.Should().BeInRange(18, 64);
    person.Email.Should().EndWith("@example.com");
    product.IsAvailable.Should().BeTrue();
}

[Theory]
[BusinessAutoData]
public void Using_BusinessAutoData(Order order)
{
    order.Status.Should().Be(OrderStatus.Created);
    order.Amount.Should().BeInRange(1000, 49999);
    order.OrderNumber.Should().StartWith("ORD");
}
```text

## CompositeAutoData: Multiple Data Source Integration

Combine multiple custom AutoData configurations by inheriting from `AutoDataAttribute` and merging Customizations from multiple Fixtures via reflection:

```csharp
// Usage - Automatically applies DomainAutoData + BusinessAutoData settings
[Theory]
[CompositeAutoData(typeof(DomainAutoDataAttribute), typeof(BusinessAutoDataAttribute))]
public void CompositeAutoData_Integrate_Multiple_Data_Sources(
    Person person, Product product, Order order)
{
    person.Age.Should().BeInRange(18, 64);       // DomainAutoData setting
    product.IsAvailable.Should().BeTrue();        // DomainAutoData setting
    order.Status.Should().Be(OrderStatus.Created); // BusinessAutoData setting
}
```text

## CollectionSizeAttribute: Control Collection Size

AutoData's default collection size is 3, which can be controlled through custom `CollectionSizeAttribute` to set the number of collection elements generated. For complete implementation and usage, see [CollectionSizeAttribute Complete Guide](references/collection-size-attribute.md).

## External Test Data Integration

Integrate external data sources like CSV, JSON with MemberAutoData while retaining AutoFixture's ability to automatically generate remaining parameters. Complete guide see [External Test Data Integration](references/external-data-integration.md).

## Data Source Design Patterns

Hierarchical data organization and reusable dataset design patterns, creating `BaseTestData` base class to uniformly manage test data paths. Complete examples see [Data Source Design Patterns](references/data-source-patterns.md).

## Collaboration with Awesome Assertions

```csharp
[Theory]
[InlineAutoData("VIP", 100000)]
[InlineAutoData("Premium", 50000)]
[InlineAutoData("Regular", 20000)]
public void AutoData_With_AwesomeAssertions_Collaboration_Customer_Level_Validation(
    string customerLevel,
    decimal expectedCreditLimit,
    [Range(1000, 15000)] decimal orderAmount,
    Customer customer,
    Order order)
{
    // Arrange
    customer.Type = customerLevel;
    customer.CreditLimit = expectedCreditLimit;
    order.Amount = orderAmount;

    // Act
    var canPlaceOrder = customer.CanPlaceOrder(order.Amount);
    var discountRate = CalculateDiscount(customer.Type, order.Amount);

    // Assert - Using Awesome Assertions syntax
    customer.Type.Should().Be(customerLevel);
    customer.CreditLimit.Should().Be(expectedCreditLimit);
    customer.CreditLimit.Should().BePositive();

    order.Amount.Should().BeInRange(1000m, 15000m);
    canPlaceOrder.Should().BeTrue();
    discountRate.Should().BeInRange(0m, 0.3m);
}

private static decimal CalculateDiscount(string customerType, decimal orderAmount)
{
    var baseDiscount = customerType switch
    {
        "VIP" => 0.15m,
        "Premium" => 0.10m,
        "Regular" => 0.05m,
        _ => 0m
    };

    var largeOrderBonus = orderAmount > 30000m ? 0.05m : 0m;
    return Math.Min(baseDiscount + largeOrderBonus, 0.3m);
}
```text

## Best Practices

### Should Do

1. **Leverage DataAnnotation**
   - Use `[StringLength]`, `[Range]` on parameters to constrain data ranges
   - Ensure generated data meets business rules

2. **Create Reusable Custom AutoData**
   - Create dedicated AutoData attributes for different domains
   - Centrally manage test data generation rules

3. **Use MemberAutoData for Complex Data**
   - Use when InlineAutoData cannot meet requirements
   - Supports variables, expressions, and external data sources

4. **Organize Test Data Sources**
   - Create hierarchical data source structures
   - Manage related data centrally

### Should Avoid

1. **Don't Use Non-Constants in InlineAutoData**
   - InlineAutoData only accepts compile-time constants
   - Use MemberAutoData for dynamic values

2. **Don't Overcomplicate CompositeAutoData**
   - Avoid combining too many AutoData sources
   - Keep configurations understandable

3. **Don't Ignore Parameter Order**
   - InlineAutoData fixed values must match parameter order
   - Wrong order causes type mismatch

## Code Templates

See example files in the [templates](./templates) folder:

- [autodata-attributes.cs](./templates/autodata-attributes.cs) - AutoData attribute family usage examples
- [external-data-integration.cs](./templates/external-data-integration.cs) - CSV/JSON external data integration
- [advanced-patterns.cs](./templates/advanced-patterns.cs) - Advanced patterns and CollectionSizeAttribute

## Relationship with Other Skills

- **autofixture-basics**: Prerequisite knowledge for this skill
- **autofixture-customization**: Customization strategies can be used for AutoData attributes
- **autofixture-nsubstitute-integration**: Next learning goal
- **awesome-assertions-guide**: Use together to improve test readability

## Reference Resources

### Original Articles

This skill content is distilled from the "Old School Software Engineer's Testing Practice - 30 Day Challenge" article series:

- **Day 12 - Combining AutoData: xUnit and AutoFixture Integration Application**
  - Article: https://ithelp.ithome.com.tw/articles/10375296
  - Sample Code: https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day12

### Official Documentation

- [AutoFixture Cheat Sheet - AutoData Theories](https://github.com/AutoFixture/AutoFixture/wiki/Cheat-Sheet#autodata-theories)
- [AutoDataAttribute API Reference](https://autofixture.io/api/AutoFixture.Xunit.AutoDataAttribute.html)
- [InlineAutoDataAttribute API Reference](https://autofixture.io/api/AutoFixture.Xunit.InlineAutoDataAttribute.html)
- [CsvHelper Official Documentation](https://joshclose.github.io/CsvHelper/)
````

