When using the fluent interface the ExecutableAttributes (Given, When, Then) are not supported.
Here is some example code to illustrate how it might be implemented:
void Main()
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
var bez = "bez";
new Foo().Given(s => s.BarAsync("let", bez, cts.Token));
}
public sealed class Foo
{
[When("foo {0} {1} baz")]
public ValueTask<int> BarAsync(string let, string bar, CancellationToken cancellationToken)
{
return ValueTask.FromResult(0);
}
}
public static class TestExtensions
{
private static IEnumerable<Type> GetParentTypes(this Type type)
{
yield return type;
if (type.BaseType == null) yield break;
yield return type.BaseType;
foreach (Type b in type.BaseType.GetParentTypes())
{
yield return b;
}
}
private static object GetValue(this MemberInfo memberInfo, object forObject)
{
switch (memberInfo.MemberType)
{
case MemberTypes.Field:
return ((FieldInfo)memberInfo).GetValue(forObject);
case MemberTypes.Property:
return ((PropertyInfo)memberInfo).GetValue(forObject);
default:
throw new NotImplementedException();
}
}
public static void Given<T>(this T model, Expression<Func<T, ValueTask<int>>> expression)
where T:class
{
var argumentProvider = (expression.Body as MethodCallExpression);
var formatString = argumentProvider
.Method
.CustomAttributes
.Where(cad => cad.AttributeType.GetParentTypes().Any(t => t == typeof(ExecutableAttribute)))
.Select(c => (ExecutableAttribute)c.Constructor.Invoke(c.ConstructorArguments.Select(c => c.Value).ToArray()))
.Select(e => e.StepTitle)
.FirstOrDefault();
for (int i = 0; i < argumentProvider.Arguments.Count; i++)
{
if (!formatString.Contains("{" + i + "}")) continue;
var argumentExpression = argumentProvider.Arguments[i];
if (argumentExpression.NodeType == ExpressionType.Constant)
{
var str = argumentExpression.ToString();
formatString = formatString.Replace("{" + i + "}", str);
}
else if(argumentExpression is MemberExpression me)
{
if (me.Expression is ConstantExpression ce)
{
var value = me.Member.GetValue(ce.Value)?.ToString();
formatString = formatString.Replace("{" + i + "}", value);
}
}
}
Console.WriteLine(formatString); // foo "let" bez baz
}
}
When using the fluent interface the
ExecutableAttributes (Given,When,Then) are not supported.Here is some example code to illustrate how it might be implemented: