尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

xUnit Theory: Working With InlineData, MemberData, ClassData

xUnit Theory: Working With InlineData, MemberData, ClassData
📅 发布时间:2026/6/18 14:09:59

原文 转发自: 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.

相关新闻

  • 现今芜湖除甲醛公司排名:2025年专业机构推荐指南
  • 2025年11月企业管理咨询公司权威推荐榜:驻厂运营与降本增效前十强深度测评
  • 2025年最新上门家教老师综合实力排行,上门家教/一对一家教上门家教机构老师推荐榜单

最新新闻

  • 地铁商用咖啡机怎么选?适配场站场景的全自动设备推荐 - 品牌2026
  • 北京黄金回收实用全指南:5家正规门店深度评测,附地址与避坑攻略 - 互联网科技品牌测评
  • 2026年辽宁资产评估专业报考指南:择校思路与院校简析 - 品牌2026
  • 3大理由:为什么开源音频编辑器Audacity能成为创作神器?
  • ⚠️2026年6月海淀LV回收清单|别盲目出手!选错门店直接亏损 - 逸程
  • 济南梵克雅宝首饰回收测评:2026年七家机构实力排行,添价收珠宝鉴定专业度摘得头名 - 薛定谔的梨花猫

日新闻

  • 2026年不锈钢卷板厂家推荐排行榜:冷轧热轧/304/201不锈钢卷板,高颜值耐腐蚀源头厂家实力精选 - 企业推荐官【官方】
  • FLUX.1-dev FP8模型实战指南:24GB以下显卡高效部署方案
  • 2026佛山长途搬家价目表:跨省跨市搬家费用完整计算指南 - 从来都是英雄出少年

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号