如何在SpecFlow中用CompareToSet动态断言不同数据服务响应
合并SpecFlow断言步骤实现动态响应校验
问题背景
我维护着EnquiryType和EnquirySource两个数据服务的自动化测试,目前在Feature文件中需要通过服务名称区分断言步骤,存在两个重复的Then方法。现在希望提取通用断言逻辑,将这两个方法合并为一个,用CompareToSet动态校验不同服务的响应结果。
当前实现代码
/// <summary> /// 请求所有EnquiryType数据 /// </summary> /// <returns></returns> [Given(@"I request all enquiry types")] public async Task RequestAllEnquiryTypes() { try { var results = await EnquiryTypesApi.GetEnquiryTypes(enquiryTypeData); enquiryTypes = new List<EnquiryTypeModel>(results.Results); FeatureSteps.statusCode = results.StatusCode; } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// <summary> /// 校验EnquiryType返回结果与预期数据匹配 /// </summary> /// <param name="data">预期的EnquiryType数据</param> [Then("The following Enquiry Type result is returned:")] public void ThenTheFollowingResultIsReturned(TechTalk.SpecFlow.Table data) { data.CompareToSet<EnquiryTypeModel>(enquiryTypes); } /// <summary> /// 请求所有EnquirySource数据 /// </summary> /// <returns></returns> [Given(@"I request all enquiry sources")] public async Task RequestAllEnquirySources() { try { var results = await EnquirySourcesApi.GetEnquirySources(enquirySourceData); enquirySources = new List<EnquirySourceModel>(results.Results); FeatureSteps.statusCode = results.StatusCode; } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// <summary> /// 校验EnquirySource返回结果与预期数据匹配 /// </summary> /// <param name="data">预期的EnquirySource数据</param> [Then("The following Enquiry Source result is returned:")] public void ThenTheFollowingResultIsReturned(TechTalk.SpecFlow.Table data) { data.CompareToSet<EnquirySourceModel>(enquirySources); }
期望实现效果
/// <summary> /// 校验返回结果与预期数据匹配 /// </summary> /// <param name="data">预期数据</param> [Then("The following result is returned:")] public void ThenTheFollowingResultIsReturned(TechTalk.SpecFlow.Table data) { data.CompareToSet(dynamicObject); }
实现方案
1. 新增公共存储字段
在Step类中添加两个字段,用于记录最近一次请求的结果集合和对应的模型类型:
private object _lastResponseResult; private Type _lastResponseModelType;
2. 修改请求步骤,统一存储结果
更新两个Given步骤,将请求结果和类型存入公共字段:
[Given(@"I request all enquiry types")] public async Task RequestAllEnquiryTypes() { try { var results = await EnquiryTypesApi.GetEnquiryTypes(enquiryTypeData); enquiryTypes = new List<EnquiryTypeModel>(results.Results); // 存储结果和类型 _lastResponseResult = enquiryTypes; _lastResponseModelType = typeof(EnquiryTypeModel); FeatureSteps.statusCode = results.StatusCode; } catch (Exception ex) { Console.WriteLine(ex.Message); } } [Given(@"I request all enquiry sources")] public async Task RequestAllEnquirySources() { try { var results = await EnquirySourcesApi.GetEnquirySources(enquirySourceData); enquirySources = new List<EnquirySourceModel>(results.Results); // 存储结果和类型 _lastResponseResult = enquirySources; _lastResponseModelType = typeof(EnquirySourceModel); FeatureSteps.statusCode = results.StatusCode; } catch (Exception ex) { Console.WriteLine(ex.Message); } }
3. 实现通用断言方法
通过反射调用泛型版本的CompareToSet方法,动态传入模型类型和结果集合:
[Then("The following result is returned:")] public void ThenTheFollowingResultIsReturned(TechTalk.SpecFlow.Table data) { if (_lastResponseResult == null || _lastResponseModelType == null) { throw new InvalidOperationException("请先执行请求步骤获取响应结果"); } // 获取CompareToSet泛型方法 var compareMethod = typeof(TableExtensions) .GetMethod(nameof(TableExtensions.CompareToSet)) .MakeGenericMethod(_lastResponseModelType); // 调用方法执行断言 compareMethod.Invoke(null, new object[] { data, _lastResponseResult }); }
注意:需要确保
TableExtensions是CompareToSet方法所在的类,根据实际命名空间调整引用。
内容的提问来源于stack exchange,提问作者Shaheem Naseeb
相关产品推荐
相关产品推荐

