惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
MyScale Blog
MyScale Blog
量子位
月光博客
月光博客
J
Java Code Geeks
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
U
Unit 42
WordPress大学
WordPress大学
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
G
Google Developers Blog
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
IT之家
IT之家
N
Netflix TechBlog - Medium
Microsoft Security Blog
Microsoft Security Blog
博客园 - 叶小钗
B
Blog
Martin Fowler
Martin Fowler
P
Proofpoint News Feed
B
Blog RSS Feed

博客园 - PanPan003

AI coding - rewind、undo 撤销操作 如何省token? - 项目 知识 固化 如何省token?--- RTK ,input 数据压缩 如何省token?--- ignore文件 如何省token?--- token 用量统计 如何省token? - 何时开启新session? 如何省token? - 更便宜的模型 处理低风险任务 如何省token?-- 如何提问?避免直接粘贴 大段文件 如何省token?- Plan ,任务拆分,从小模型开始 如何省token?-rewind(todo) 如何省token?- handoff (todo) 如何省token? - compact,压缩上下文 Skill - superpowers skill - mattpocock OpenCode 安装 claude code 安装 npm config AI - coding - links/summary SSH 本地端口转发 --- VM中ubuntu service 可被 Windows 访问 内网穿透 - devtunnel Linux 虚拟机 反向代理 - 到宿主机 - decimal, double在 c#中的区别 python environment settings docker network - container networking KEDA — Kubernetes Based Event Driven Auto scaling(转载) rabbit MQ —— ha-sync-mode. message 同步/ 丢失 in new pods rabbit MQ —— ha-mode, message 同步策列:所有nodes or one nodes 博文阅读密码验证 - 博客园 Kubernetes hpa container scale up/ down 原理 in kubernetes
xUnit Theory: Working With InlineData, MemberData, ClassData
PanPan003 · 2025-11-25 · via 博客园 - PanPan003

原文 转发自: https://hamidmosalla.com/2017/02/25/xunit-theory-working-with-inlinedata-memberdata-classdata/

xUnit Theory: Working With InlineData, MemberData, ClassData

xUnit support two different types of unit test, Fact and Theory. We use xUnit Fact when we have some criteria that always must be met, regardless of data. For example, when we test a controller’s action to see if it’s returning the correct view. xUnit Theory on the other hand depends on set of parameters and its data, our test will pass for some set of data and not the others. We have a theory which postulate that with this set of data, this will happen. In this post, I’m going to discuss what are our options when we need to feed a theory with a set of data and see why and when to use them.

xUnit Theory With InlineData

This is a simplest form of testing our theory with data, but it has its drawbacks, which is we don’t have much flexibility, let’s see how it works first.

public class ParameterizedTests
{
   public bool IsOddNumber(int number)
   {
       return number % 2 != 0;
   }

  [Theory]
  [InlineData(5, 1, 3, 9)]
  [InlineData(7, 1, 5, 3)]
  public void AllNumbers_AreOdd_WithInlineData(int a, int b, int c, int d)
  {
      Assert.True(IsOddNumber(a));
      Assert.True(IsOddNumber(b));
      Assert.True(IsOddNumber(c));
      Assert.True(IsOddNumber(d));
  }
}

As you see above, we provide some values in InlineData and xUnit will create two tests and every time populates the test case arguments with what we’ve passed into InlineData. I said there are some limitation on what we can pass in InlineData attribute, look what happens when we try to pass a new instance of some object:

InlineData Attribute Doesn't Work With Complex Types

We can pass this kind of data to our theory with ClassData or MemberData.

xUnit Theory With ClassData

ClassData is another attribute that we can use with our theory, with ClassData we have more flexibility and less clutter:

public class TestDataGenerator : IEnumerable<object[]>
{
    private readonly List<object[]> _data = new List<object[]>
    {
        new object[] {5, 1, 3, 9},
        new object[] {7, 1, 5, 3}
    };

    public IEnumerator<object[]> GetEnumerator() => _data.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

public class ParameterizedTests
{
    public bool IsOddNumber(int number)
    {
        return number % 2 != 0;
    }

    [Theory]
    [ClassData(typeof(TestDataGenerator))]
    public void AllNumbers_AreOdd_WithClassData(int a, int b, int c, int d)
    {
        Assert.True(IsOddNumber(a));
        Assert.True(IsOddNumber(b));
        Assert.True(IsOddNumber(c));
        Assert.True(IsOddNumber(d));
    }
}

Here I’ve created a class that inherits from IEnumerable<object[]>, note that it has to be an object, otherwise xUnit will throws an error. Next I create a private list of object that I intend to pass to my theory and finally I implemented the GetEnumerator method with piggybacking on our list Enumerator. Now we can pass our TestDataGenerator class to ClassData attribute and the returned data form that class will populate the test case’s parameters.

xUnit Theory With MemberData

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class TestDataGenerator : IEnumerable<object[]>
{
    public static IEnumerable<object[]> GetNumbersFromDataGenerator()
    {
        yield return new object[] { 5, 1, 3, 9 };
        yield return new object[] { 7, 1, 5, 3 };
    }

    public static IEnumerable<object[]> GetPersonFromDataGenerator()
    {
        yield return new object[]
        {
            new Person {Name = "Tribbiani", Age = 56},
            new Person {Name = "Gotti", Age = 16},
            new Person {Name = "Sopranos", Age = 15},
            new Person {Name = "Corleone", Age = 27}
        };

        yield return new object[]
        {
            new Person {Name = "Mancini", Age = 79},
            new Person {Name = "Vivaldi", Age = 16},
            new Person {Name = "Serpico", Age = 19},
            new Person {Name = "Salieri", Age = 20}
        };
    }
}

public class ParameterizedTests
{
    public bool IsOddNumber(int number)
    {
        return number % 2 != 0;
    }

    public bool IsAboveFourteen(Person person)
    {
        return person.Age > 14;
    }

    public static IEnumerable<object[]> GetNumbers()
    {
        yield return new object[] { 5, 1, 3, 9 };
        yield return new object[] { 7, 1, 5, 3 };
    }

    [Theory]
    [MemberData(nameof(GetNumbers))]
    public void AllNumbers_AreOdd_WithMemberData(int a, int b, int c, int d)
    {
        Assert.True(IsOddNumber(a));
        Assert.True(IsOddNumber(b));
        Assert.True(IsOddNumber(c));
        Assert.True(IsOddNumber(d));
    }

    [Theory]
    [MemberData(nameof(TestDataGenerator.GetNumbersFromDataGenerator), MemberType = typeof(TestDataGenerator))]
    public void AllNumbers_AreOdd_WithMemberData_FromDataGenerator(int a, int b, int c, int d)
    {
        Assert.True(IsOddNumber(a));
        Assert.True(IsOddNumber(b));
        Assert.True(IsOddNumber(c));
        Assert.True(IsOddNumber(d));
    }

    [Theory]
    [MemberData(nameof(TestDataGenerator.GetPersonFromDataGenerator), MemberType = typeof(TestDataGenerator))]
    public void AllPersons_AreAbove14_WithMemberData_FromDataGenerator(Person a, Person b, Person c, Person d)
    {
        Assert.True(IsAboveFourteen(a));
        Assert.True(IsAboveFourteen(b));
        Assert.True(IsAboveFourteen(c));
        Assert.True(IsAboveFourteen(d));
    }
}

MemberData gives us the same flexibility but without the need for a class. I’ve created an static method called GetNumbers which is local to our test class, and I passed it to AllNumbers_AreOdd_WithMemberData‘s MemberData attribute. But it doesn’t need to be a local method, we can pass a method from another class too, as I did with AllNumbers_AreOdd_WithMemberData_FromDataGenerator test case. Also you’re not limited to primitive types, I’ve generated and passed a complex object called Person to AllPersons_AreAbove14_WithMemberData_FromDataGenerator test, and this was something that we couldn’t do with InlineData attribute, but we can do with ClassData or MemberData attribute.