我在Xuit中进行了此集成测试。
[Fact]
public async Task AddCampaignAsync_GivenUniqueTitle_GivenGoodDates_ShouldPass()
{
var campaign = new Campaign
{
Title = "Test",
StartDate = new DateTime(2021, 6, 5),
EndDate = new DateTime(2021, 6, 6)
};
using (var context = new CampaignDbContext(_options))
{
_campaignService = new CampaignService(context);
var actualCampaign = await _campaignService.AddCampaignAsync(campaign);
Assert.Equal(campaign.Title, actualCampaign.Title);
Assert.Equal(campaign.StartDate, actualCampaign.StartDate);
Assert.Equal(campaign.EndDate, actualCampaign.EndDate);
}
}
CCD_ 1的代码如下:
public async Task<Campaign> AddCampaignAsync(Campaign campaign)
{
if (campaign.EndDate != null) {
if (campaign.StartDate > campaign.EndDate)
{
throw new Exception("The campaign start date cannot be greater than end date");
}
}
await _context.Campaigns.AddAsync(campaign);
await _context.SaveChangesAsync();
return campaign;
}
它运行良好。但是,我是否可以将campaign
的集合作为测试数据传递,而不是仅将一个campaign
对象作为测试数据?
首先,从测试方法中删除campaign
,并将其作为该方法的参数。然后移除Fact
属性并添加Theory
属性。Fact
属性通常用于测试不涉及数据集合的位置。需要对不同数据多次运行的测试通常用Theory
:进行修饰
[Theory]
public async Task AddCampaignAsync_GivenUniqueTitle_GivenGoodDates_ShouldPass(Campaign campaign)
{
using (var context = new CampaignDbContext(_options))
{
_campaignService = new CampaignService(context);
var actualCampaign = await _campaignService.AddCampaignAsync(campaign);
Assert.Equal(campaign.Title, actualCampaign.Title);
Assert.Equal(campaign.StartDate, actualCampaign.StartDate);
Assert.Equal(campaign.EndDate, actualCampaign.EndDate);
}
}
有几个选项可以为测试方法提供测试数据。
1.继承自TheoryData<T>
CCD_ 10用于为测试方法的参数提供数据。它为不同的方法参数长度定义了几个通用重载。AddCampaignAsync
1有一个参数Campaign
,因此从TheoryData<Campaign>
继承:
public class CampaignData : TheoryData<Campaign>
{
public CampaignData()
{
Add(new Campaign { Title = "Test1", StartDate = new DateTime(2021, 1, 5), EndDate = new DateTime(2021, 10, 6) });
Add(new Campaign { Title = "Test2", StartDate = new DateTime(2021, 2, 5), EndDate = new DateTime(2021, 9, 6) });
Add(new Campaign { Title = "Test3", StartDate = new DateTime(2021, 3, 5), EndDate = new DateTime(2021, 8, 6) });
Add(new Campaign { Title = "Test4", StartDate = new DateTime(2021, 4, 5), EndDate = new DateTime(2021, 7, 6) });
}
}
在构造函数中,调用Add
方法将Campaign
对象添加到集合中。现在您可以使用ClassData
属性:
[Theory]
[ClassData(typeof(CampaignData))]
public async Task AddCampaignAsync_GivenUniqueTitle_GivenGoodDates_ShouldPass(Campaign campaign)
{
using (var context = new CampaignDbContext(_options))
{
_campaignService = new CampaignService(context);
var actualCampaign = await _campaignService.AddCampaignAsync(campaign);
Assert.Equal(campaign.Title, actualCampaign.Title);
Assert.Equal(campaign.StartDate, actualCampaign.StartDate);
Assert.Equal(campaign.EndDate, actualCampaign.EndDate);
}
}
使用ClassData(typeof(CampaignData))
,您将告诉xUnit,CampaignData
类具有此方法需要调用的所有参数。
2.使用MemberData
如果不想创建新类,也可以将集合项定义为同一类的静态成员。在具有AddCampaignAsync_GivenUniqueTitle_GivenGoodDates_ShouldPass
方法的同一类中,定义一个静态属性或字段,如下所示。此属性的类型为IEnumerable<object[]>
。它是object[]
阵列的集合。集合中的每个object
数组都为测试方法定义了一个参数列表,您的测试方法有一个参数Campaign campaign
。因此,每个对象数组都可以包含一个Campaign
对象。然后在AddCampaignAsync_GivenUniqueTitle_GivenGoodDates_ShouldPass
上添加具有属性名称的MemberData
属性:
class YourTestClass
{
public static IEnumerable<object[]> Campaigns => new List<object[]>
{
new object[]
{
new Campaign { Title = "Test1", StartDate = new DateTime(2021, 1, 5), EndDate = new DateTime(2021, 10, 6) },
new Campaign { Title = "Test2", StartDate = new DateTime(2021, 2, 5), EndDate = new DateTime(2021, 9, 6) },
new Campaign { Title = "Test3", StartDate = new DateTime(2021, 3, 5), EndDate = new DateTime(2021, 8, 6) },
new Campaign { Title = "Test4", StartDate = new DateTime(2021, 4, 5), EndDate = new DateTime(2021, 7, 6) }
}
};
[Theory]
[MemberData(nameof(Campaigns))]
public async Task AddCampaignAsync_GivenUniqueTitle_GivenGoodDates_ShouldPass(Campaign campaign)
{
using (var context = new CampaignDbContext(_options))
{
_campaignService = new CampaignService(context);
var actualCampaign = await _campaignService.AddCampaignAsync(campaign);
Assert.Equal(campaign.Title, actualCampaign.Title);
Assert.Equal(campaign.StartDate, actualCampaign.StartDate);
Assert.Equal(campaign.EndDate, actualCampaign.EndDate);
}
}
}
这将使用Campaigns
属性的object
数组中的每个Campaign
对象调用方法AddCampaignAsync_GivenUniqueTitle_GivenGoodDates_ShouldPass
。
如果您只有几个Campaign
对象要测试,那么Sergei使用InlineData
属性的方法是一个不错的选择。
参考:https://andrewlock.net/creating-strongly-typed-xunit-theory-test-data-with-theorydata/(你可以在这里找到更多的方法(
您可以使用数据驱动的测试。
例如:
[Theory]
[InlineData("Test1", "2021-06-05", "2021-06-06")]
[InlineData("Test2", "2021-06-07", "2021-06-08")]
public async Task AddCampaignAsync_GivenUniqueTitle_GivenGoodDates_ShouldPass(string title, DateTime startDate, DateTime endDate)
{
var campaign = new Campaign
{
Title = title,
StartDate = startDate,
EndDate = endDate
};
...
您可以在此处找到更多示例:https://andrewlock.net/creating-parameterised-tests-in-xunit-with-inlinedata-classdata-and-memberdata/