[英]AutoFixture: resolving IEnumerable<T>, Unable to cast object of type 'ConvertedEnumerable` to List
I tried to use AutoFixture to generate test data for classes that have IEnumerable members.我尝试使用 AutoFixture 为具有 IEnumerable 成员的类生成测试数据。
AutoFixture test code: AutoFixture测试代码:
var fixture = new Fixture();
fixture.Customize<NotificationDto>(c => c.Without(r => r.IntegrationModel));
NotificationDto notificationDto = fixture.Create<NotificationDto>();
Class: Class:
public class NotificationDto
{
public NotificationDto()
{
To = new List<RecipientDto>();
}
public Guid Id { get; set; }
public IIntegrationEventModel IntegrationModel { get; set; }
public IEnumerable<RecipientDto> To { get; set; }
}
During debugging of code代码调试期间
public CreateNotificationCommand(NotificationDto notificationDto)
{
...
To = (List<RecipientDto>)(notificationDto.To ?? new List<RecipientDto>());
}
Getting below error:出现以下错误:
UpdateNotificationFromAwsSnsCommandHandlers_UpdateNotificationToSuccess Duration: 8.9 sec Message: System.InvalidCastException : Unable to cast object of type 'ConvertedEnumerable`1[Notification.Core.Notification.Dto.SolrDto.RecipientSolrDto]' to type 'System.Collections.Generic.List`1[Notification.Core.Notification.Dto.SolrDto.RecipientSolrDto]'. Stack Trace: CreateNotificationCommand.ctor(NotificationDto notificationDto) line 31 UpdateNotificationFromAwsSnsCommandHandlersTester.SetAutoData_UpdateNotificationFromAwsSnsCommandHandlers_UpdateNotificationToNotDelivered() line 60 UpdateNotificationFromAwsSnsCommandHandlersTester.UpdateNotificationFromAwsSnsCommandHandlers_UpdateNotificationToSuccess() line 75 GenericAdapter`1.GetResult() AsyncToSyncAdapter.Await(Func`1 invoke) TestMethodCommand.RunTestMethod(TestExecutionContext context) TestMethodCommand.Execute(TestExecutionContext context) c__DisplayClass1_0.b__0() BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
Please help me?请帮我?
To
is an IEnumerable
, so it is not guaranteed to be a List
, so this cast is not guaranteed to work (in your unit test AutoFixture does not create a list, for example). To
是一个IEnumerable
,所以它不能保证是一个List
,所以这个演员不能保证工作(例如,在你的单元测试中,AutoFixture 不会创建一个列表)。 You can change your code to:您可以将代码更改为:
To = notificationDto.To ?? Enumerable.Empty<RecipientDto>();
or something like:或类似的东西:
To = notificationDto.To as List<RecipientDto>
?? notificationDto.To?.ToList()
?? new List<RecipientDto>();
Or change the signature of To
to List<RecipientDto>
.或者将To
的签名更改为List<RecipientDto>
。
The exception is thrown because notificationDto.To
isn't necessarily List<RecipientDto>
at runtime, it can be an array of RecipientDto
or any other type implicitly casted to IEnumerable<RecipientDto>
.抛出异常是因为notificationDto.To
在运行时不一定是List<RecipientDto>
,它可以是RecipientDto
的数组或隐式转换为IEnumerable<RecipientDto>
的任何其他类型。 Hence, when notificationDto.To
has different runtime type from List<RecipientDto>
the InvalidCastException
is thrown.因此,当notificationDto.To
具有与List<RecipientDto>
不同的运行时类型时,将抛出InvalidCastException
。
To fix this you can either just remove casting to the list and everything should work fine or have Enumerable.Empty<RecipientDto>()
on the right side of the operator ( for both only if To
on the right side of =
is IEnumerable<RecipientDto>
):要解决此问题,您可以只删除对列表的强制转换,一切都应该正常工作,或者在运算符的右侧使用Enumerable.Empty<RecipientDto>()
(只有当=
右侧的To
是IEnumerable<RecipientDto>
):
1. To = notificationDto.To ?? new List<RecipientDto>();
2. To = notificationDto.To ?? Enumerable.Empty<RecipientDto>();
The first approach works because the result type of the expression in this case will be IEnumerable<RecipientDto>
.第一种方法有效,因为在这种情况下表达式的结果类型将是IEnumerable<RecipientDto>
。 This follows from the specification for the operator ??
这遵循操作员规范??
https://learn.microsoft.com/en-us/do.net/csharp/language-reference/language-specification/expressions#1114-the-null-coalescing-operator . https://learn.microsoft.com/en-us/do.net/csharp/language-reference/language-specification/expressions#1114-the-null-coalescing-operator 。
We're interested in this part of the spec:我们对规范的这一部分感兴趣:
if
A
is not a nullable type ( but a reference type ) and an implicit conversion exists fromb
toA
, the result type isA
.如果A
不是可空类型(而是引用类型)并且存在从b
到A
的隐式转换,则结果类型为A
At run-time,a
is first evaluated.在运行时,首先评估a
。 Ifa
is notnull
,a
becomes the result.如果a
不是null
,则a
成为结果。 Otherwise,b
is evaluated and converted to typeA
, and this becomes the result.`否则,b
被评估并转换为类型A
,这成为结果。
Where A
is the type of a
.其中A
是a
的类型。
In your case a
is notificationDto.To
and b
is new List<RecipientDto>()
, therefore A
is IEnumerable<RecipientDto>
.在您的情况下, a
是notificationDto.To
并且b
是new List<RecipientDto>()
,因此A
是IEnumerable<RecipientDto>
。 Since IEnumerable<RecipientDto>
is not a nullable type and there is a conversion from new List<RecipientDto>
to IEnumerable<RecipientDto>
the result type of the expression will be also IEnumerable<RecipientDto>
.由于IEnumerable<RecipientDto>
不是可空类型,并且存在从new List<RecipientDto>
到IEnumerable<RecipientDto>
的转换,因此表达式的结果类型也将是IEnumerable<RecipientDto>
。 Hence if To
is already IEnumerable<RecipientDto>
you don't need to do any casting.因此,如果To
已经是IEnumerable<RecipientDto>
你不需要做任何转换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.