Tar*_*asB 7 .net c# fluent-assertions
我想验证(断言)我的DTO对象上的某些属性是否已设置.我试图用Fluent Assertions来做,但以下代码似乎不起作用:
mapped.ShouldHave().Properties(
x => x.Description,
...more
x => x.Id)
.Should().NotBeNull();
Run Code Online (Sandbox Code Playgroud)
是否可以通过Fluent Assertions或其他工具实现这一目标?Fluent断言具有ShouldBeEquivalentTo,但实际上我只关心那些是不是空/空,所以我无法使用.
当然我可以在每个属性级别上做一个Assert,但是对一些更优雅的方式感兴趣.
实际上,Properties方法return PropertiesAssertion,仅具有EqualTo用于相等比较的方法。没有 NotEqualTo方法或NotNull。在您的测试中,您预期PropertiesAssertion不会是null,这就是为什么它将始终通过的原因。
您可以实现一个AssertionHelper静态类并传递一个Funcs 数组,用于验证对象。这是一个非常幼稚的实现,您不会得到很好的错误报告,但我只是展示了总体思路
public static void CheckAllPropertiesAreNotNull<T>(this T objectToInspect,
params Func<T, object>[] getters)
{
if (getters.Any(f => f(objectToInspect) == null))
Assert.Fail("some of the properties are null");
}
Run Code Online (Sandbox Code Playgroud)
现在此测试将失败并some of the properties are null显示消息
var myDto = new MyDto();
myDto.CheckAllPropertiesAreNotNull(x => x.Description,
x => x.Id);
Run Code Online (Sandbox Code Playgroud)
该解决方案存在两个问题:
Id属性为值类型,getter(objectToInspect) == null则始终为false要解决第一点,您可以:
CheckAllPropertiesAreNotNull,每个重载将具有不同数量的Generic Func<TInput, TFirstOutput> firstGetter,然后将每个getter的返回值与对应的default(TFirstOutput) Activator创建默认实例并调用Equals我将告诉您第二种情况。您可以创建一个IsDefault方法,该方法将接受类型为参数的参数object(请注意,这可以是装箱的int):
private static bool IsDefault(this object value)
{
if (value == null)
return true;
if (!value.GetType().IsValueType) //if a reference type and not null
return false;
//all value types should have a parameterless constructor
var defaultValue = Activator.CreateInstance(value.GetType());
return value.Equals(defaultValue);
}
Run Code Online (Sandbox Code Playgroud)
现在,我们的总体代码中,该处理程序的值类型将如下所示:
public static void CheckAllPropertiesAreNotDefault<T>(this T objectToInspect,
params Func<T, object>[] getters)
{
if (getters.Any(f => f(objectToInspect).IsDefault()))
Assert.Fail("some of the properties are not null");
}
Run Code Online (Sandbox Code Playgroud)
要解决第二点,您可以传递一个Expression<Func<T, object>>[] getters,其中将包含有关称为属性的信息。创建一个方法GetName,该方法将接受Expression<Func<T, object>>并返回调用的属性名称
public static string GetName<T>(Expression<Func<T, object>> exp)
{
var body = exp.Body as MemberExpression;
//return type is an object, so type cast expression will be added to value types
if (body == null)
{
var ubody = (UnaryExpression)exp.Body;
body = ubody.Operand as MemberExpression;
}
return body.Member.Name;
}
Run Code Online (Sandbox Code Playgroud)
现在生成的代码如下所示:
public static void CheckAllPropertiesAreNotDefault<T>(this T objectToInspect,
params Expression<Func<T, object>>[] getters)
{
var defaultProperties = getters.Where(f => f.Compile()(objectToInspect).IsDefault());
if (defaultProperties.Any())
{
var commaSeparatedPropertiesNames = string.Join(", ", defaultProperties.Select(GetName));
Assert.Fail("expected next properties not to have default values: " + commaSeparatedPropertiesNames);
}
}
Run Code Online (Sandbox Code Playgroud)
现在给我打电话
myDto.CheckAllPropertiesAreNotDefault(x => x.Description,
x => x.Id);
Run Code Online (Sandbox Code Playgroud)
我懂了
预期的下一个属性不具有默认值:说明,ID
错误信息。在我的Dto中Description是一个string并且Id是值类型int。如果我将该属性设置为一些非默认值,则不会出现错误,并且测试将通过。
| 归档时间: |
|
| 查看次数: |
8602 次 |
| 最近记录: |