Xunit 2.3.0 无法将日期作为内联参数传递
Xunit 2.3.0 Unable to pass dates as inline params
在 xUnit 2.2 和之前的版本中,我们能够在实现 Theory 时将日期字符串作为内联数据传递。
[Theory]
[InlineData("title 1", "testing 1", 1, "Educational", "2017-3-1", "2018-12-31")]
[InlineData("title 2", "testing 2", 2, "Self Employment", "2017-2-1", "2018-2-28")]
public async Task WhenPassingCorrectData_SuccessfullyCreate(
string title,
string description,
int categoryId,
string category,
DateTime startDate,
DateTime endDate)
{
}
但是随着 2.3 更新,这似乎被破坏了,Visual studio 给出了编译错误。
The value is not convertible to the method parameter 'startDate' of
type 'System.DateTime
对于必须以字符串形式接收日期并将其转换为测试方法的其他问题,是否有人有解决方法?
这会不会是这个版本中的一个临时错误,会在以后的版本中修复吗?
PS:我在 VS2017 上的 .netcore 项目上使用 xUnit
您可以使用 MemberDataAttribute
使其明确:-
public static readonly object[][] CorrectData =
{
new object[] { "title 1", "testing 1", 1, "Educational", new DateTime(2017,3,1), new DateTime(2018,12,31)},
new object[] { "title 2", "testing 2", 2, "Self Employment", new DateTime(2017, 2, 1), new DateTime(2018, 2, 28)}
};
[Theory, MemberData(nameof(CorrectData))]
public async Task WhenPassingCorrectData_SuccessfullyCreate(string title, string description, int categoryId, string category, DateTime startDate, DateTime endDate)
{
}
(您也可以使用 属性 return IEnumerable<object[]>
,您通常会使用 yield return
enumerator syntax,但我相信以上是最易读的语法C#目前必须提供)
这是将强类型测试数据传递给 xUnit 测试的好方法
public class SampleData
{
public int A { get; set; }
public int B { get; set; }
public int C => A + B;
}
public class UnitTest1
{
/// <summary>
/// The test data must have this return type and should be static
/// </summary>
public static IEnumerable<object[]> TestData
{
get
{
//Load the sample data from some source like JSON or CSV here.
var sampleDataList = new List<SampleData>
{
new SampleData { A = 1, B = 2 },
new SampleData { A = 3, B = 2 },
new SampleData { A = 2, B = 2 },
new SampleData { A = 3, B = 23 },
new SampleData { A = 43, B = 2 },
new SampleData { A = 3, B = 22 },
new SampleData { A = 8, B = 2 },
new SampleData { A = 7, B = 25 },
new SampleData { A = 6, B = 27 },
new SampleData { A = 5, B = 2 }
};
var retVal = new List<object[]>();
foreach(var sampleData in sampleDataList)
{
//Add the strongly typed data to an array of objects with one element. This is what xUnit expects.
retVal.Add(new object[] { sampleData });
}
return retVal;
}
}
/* Alternate form
public static IEnumerable<object[]> TestData()
{
yield return new [] { new SampleData { A = 1, B = 2 } };
yield return new [] { new SampleData { A = 3, B = 2 } };
yield return new [] { new SampleData { A = 2, B = 2 } };
yield return new [] { new SampleData { A = 3, B = 23 } };
yield return new [] { new SampleData { A = 43, B = 2 } };
yield return new [] { new SampleData { A = 3, B = 22 } };
yield return new [] { new SampleData { A = 8, B = 2 } };
yield return new [] { new SampleData { A = 7, B = 25 } };
yield return new [] { new SampleData { A = 6, B = 27 } };
yield return new [] { new SampleData { A = 5, B = 2 } };
}
*/
/* Or:
public static IEnumerable<object[]> TestData() =>
from x in new[] {
new SampleData { A = 1, B = 2 },
new SampleData { A = 3, B = 2 },
new SampleData { A = 2, B = 2 },
new SampleData { A = 3, B = 23 },
new SampleData { A = 43, B = 2 },
new SampleData { A = 3, B = 22 },
new SampleData { A = 8, B = 2 },
new SampleData { A = 7, B = 25 },
new SampleData { A = 6, B = 27 },
new SampleData { A = 5, B = 2 } }
select new object[] { x};
*/
/// <summary>
/// Specify the test data property with an attribute. This method will get executed
/// for each SampleData object in the list
/// </summary>
[Theory, MemberData(nameof(TestData))]
public void Test1(SampleData sampleData)
{
Assert.Equal(sampleData.A + sampleData.B, sampleData.C);
}
}
目前更好的方法是使用 TheoryData,这样您就可以使用强类型输入。
Creating strongly typed xUnit theory test data with TheoryData
TheoryData<DateTime> MemberData = new TheoryData<DateTime>
{
DateTime.Now,
new DateTime(),
DateTime.Max
}
看来此错误已在 v2.4.0+ 中修复(此功能至少在 v2.3.1 中停止工作?)
如果无法将 xunit 升级到带有修复程序的版本,那么也许可以执行与 xunit 隐式执行的操作相同的操作:
https://github.com/xunit/xunit/blob/main/src/xunit.v3.core/Sdk/Reflection/Reflector.cs#L63-L69
[Theory]
[InlineData("title 1", "testing 1", 1, "Educational", "2017-3-1", "2018-12-31")]
[InlineData("title 2", "testing 2", 2, "Self Employment", "2017-2-1", "2018-2-28")]
public async Task WhenPassingCorrectData_SuccessfullyCreate(
string title,
string description,
int categoryId,
string category,
string startDate, // <-- change from `DateTime` to `string`
string endDate) // <-- change from `DateTime` to `string`
{
var expectedStartDate = DateTime.Parse(startDate); // <-- add this
var expectedEndDate = DateTime.Parse(endDate); // <-- add this
// rest of test ...
}
否则,如果有更复杂的测试,那么可能会像其他人建议的那样使用 MemberDataAttribute
。
在 xUnit 2.2 和之前的版本中,我们能够在实现 Theory 时将日期字符串作为内联数据传递。
[Theory]
[InlineData("title 1", "testing 1", 1, "Educational", "2017-3-1", "2018-12-31")]
[InlineData("title 2", "testing 2", 2, "Self Employment", "2017-2-1", "2018-2-28")]
public async Task WhenPassingCorrectData_SuccessfullyCreate(
string title,
string description,
int categoryId,
string category,
DateTime startDate,
DateTime endDate)
{
}
但是随着 2.3 更新,这似乎被破坏了,Visual studio 给出了编译错误。
The value is not convertible to the method parameter 'startDate' of type 'System.DateTime
对于必须以字符串形式接收日期并将其转换为测试方法的其他问题,是否有人有解决方法?
这会不会是这个版本中的一个临时错误,会在以后的版本中修复吗?
PS:我在 VS2017 上的 .netcore 项目上使用 xUnit
您可以使用 MemberDataAttribute
使其明确:-
public static readonly object[][] CorrectData =
{
new object[] { "title 1", "testing 1", 1, "Educational", new DateTime(2017,3,1), new DateTime(2018,12,31)},
new object[] { "title 2", "testing 2", 2, "Self Employment", new DateTime(2017, 2, 1), new DateTime(2018, 2, 28)}
};
[Theory, MemberData(nameof(CorrectData))]
public async Task WhenPassingCorrectData_SuccessfullyCreate(string title, string description, int categoryId, string category, DateTime startDate, DateTime endDate)
{
}
(您也可以使用 属性 return IEnumerable<object[]>
,您通常会使用 yield return
enumerator syntax,但我相信以上是最易读的语法C#目前必须提供)
这是将强类型测试数据传递给 xUnit 测试的好方法
public class SampleData
{
public int A { get; set; }
public int B { get; set; }
public int C => A + B;
}
public class UnitTest1
{
/// <summary>
/// The test data must have this return type and should be static
/// </summary>
public static IEnumerable<object[]> TestData
{
get
{
//Load the sample data from some source like JSON or CSV here.
var sampleDataList = new List<SampleData>
{
new SampleData { A = 1, B = 2 },
new SampleData { A = 3, B = 2 },
new SampleData { A = 2, B = 2 },
new SampleData { A = 3, B = 23 },
new SampleData { A = 43, B = 2 },
new SampleData { A = 3, B = 22 },
new SampleData { A = 8, B = 2 },
new SampleData { A = 7, B = 25 },
new SampleData { A = 6, B = 27 },
new SampleData { A = 5, B = 2 }
};
var retVal = new List<object[]>();
foreach(var sampleData in sampleDataList)
{
//Add the strongly typed data to an array of objects with one element. This is what xUnit expects.
retVal.Add(new object[] { sampleData });
}
return retVal;
}
}
/* Alternate form
public static IEnumerable<object[]> TestData()
{
yield return new [] { new SampleData { A = 1, B = 2 } };
yield return new [] { new SampleData { A = 3, B = 2 } };
yield return new [] { new SampleData { A = 2, B = 2 } };
yield return new [] { new SampleData { A = 3, B = 23 } };
yield return new [] { new SampleData { A = 43, B = 2 } };
yield return new [] { new SampleData { A = 3, B = 22 } };
yield return new [] { new SampleData { A = 8, B = 2 } };
yield return new [] { new SampleData { A = 7, B = 25 } };
yield return new [] { new SampleData { A = 6, B = 27 } };
yield return new [] { new SampleData { A = 5, B = 2 } };
}
*/
/* Or:
public static IEnumerable<object[]> TestData() =>
from x in new[] {
new SampleData { A = 1, B = 2 },
new SampleData { A = 3, B = 2 },
new SampleData { A = 2, B = 2 },
new SampleData { A = 3, B = 23 },
new SampleData { A = 43, B = 2 },
new SampleData { A = 3, B = 22 },
new SampleData { A = 8, B = 2 },
new SampleData { A = 7, B = 25 },
new SampleData { A = 6, B = 27 },
new SampleData { A = 5, B = 2 } }
select new object[] { x};
*/
/// <summary>
/// Specify the test data property with an attribute. This method will get executed
/// for each SampleData object in the list
/// </summary>
[Theory, MemberData(nameof(TestData))]
public void Test1(SampleData sampleData)
{
Assert.Equal(sampleData.A + sampleData.B, sampleData.C);
}
}
目前更好的方法是使用 TheoryData,这样您就可以使用强类型输入。 Creating strongly typed xUnit theory test data with TheoryData
TheoryData<DateTime> MemberData = new TheoryData<DateTime>
{
DateTime.Now,
new DateTime(),
DateTime.Max
}
看来此错误已在 v2.4.0+ 中修复(此功能至少在 v2.3.1 中停止工作?)
如果无法将 xunit 升级到带有修复程序的版本,那么也许可以执行与 xunit 隐式执行的操作相同的操作:
https://github.com/xunit/xunit/blob/main/src/xunit.v3.core/Sdk/Reflection/Reflector.cs#L63-L69
[Theory]
[InlineData("title 1", "testing 1", 1, "Educational", "2017-3-1", "2018-12-31")]
[InlineData("title 2", "testing 2", 2, "Self Employment", "2017-2-1", "2018-2-28")]
public async Task WhenPassingCorrectData_SuccessfullyCreate(
string title,
string description,
int categoryId,
string category,
string startDate, // <-- change from `DateTime` to `string`
string endDate) // <-- change from `DateTime` to `string`
{
var expectedStartDate = DateTime.Parse(startDate); // <-- add this
var expectedEndDate = DateTime.Parse(endDate); // <-- add this
// rest of test ...
}
否则,如果有更复杂的测试,那么可能会像其他人建议的那样使用 MemberDataAttribute
。