如何用贴图选项模拟贴图资料。

问题描述 投票:0回答:1

我有一个映射配置文件,使用 IDictionary<string, object> 来传递一个值。我是这样使用的。

var viewModel = _mapper.Map<TransactionDetailsViewModel>(
    transaction,
    opt =>
    {
        opt.Items.Add( typeof(IClockService).Name, _systemClock );
    }
);

我试着在单元测试中模拟它,但总是得到... NotSupportedException 在这里。

Mock<IMapper> _mockMapper = new Mock<IMapper>();
_mockMapper
    .Setup(
        mm => mm.Map<TransactionDetailsViewModel>(
            domainModel,
            opt => opt.Items.Add( typeof(IClockService).Name, _systemClock )
        )
    )
    .Returns( viewModel );

正确的模拟方法是什么?

下面是 StackTrace :

 at Moq.MatcherFactory.CreateMatcher(Expression expression)
   at Moq.MatcherFactory.CreateMatcher(Expression argument, ParameterInfo parameter)
   at Moq.MatcherFactory.CreateMatchers(IReadOnlyList`1 arguments, ParameterInfo[] parameters)
   at Moq.InvocationShape..ctor(LambdaExpression expression, MethodInfo method, IReadOnlyList`1 arguments, Boolean exactGenericTypeArguments)
   at Moq.ExpressionExtensions.<Split>g__Split|4_1(Expression e, Expression& r, InvocationShape& p)
   at Moq.ExpressionExtensions.Split(LambdaExpression expression)
   at Moq.Mock.Setup(Mock mock, LambdaExpression expression, Condition condition)
   at Moq.Mock`1.Setup[TResult](Expression`1 expression)
   at Hosts.Api.Tests.TransactionsControllerTests.GetTransaction_WhenAdvance_ConvertsSpread() in C:\Users\RS\source\repos\Project\src\UnitTests\Hosts.Api.Tests\Operations\Transactions\TransactionsControllerTests.cs:line 211

留言内容:我有一个使用IDictionary的映射配置文件。

Unsupported expression: opt => 
opt.Items.Add(Services.ClockService.Interfaces.IClockService.Name,
value(Hosts.Api.Tests.TransactionsControllerTests)._systemClock)
c# .net-core automapper moq
1个回答
1
投票

通常我不会模拟映射器,我认为大多数时候集成测试映射配置文件是一件好事,然而我时常会根据需要做。

首先为选项指定一个匹配器。

mapperMock.Setup(x => x.Map<TransactionDetailsViewModel>(
        transaction,
        It.Is<Action<IMappingOperationOptions>>(opt => AddsItem(opt, nameof(IClockService), systemClock)))).Returns(viewModel);

你不能对委托本身进行匹配,但在这种情况下,你可以对它所做的事情进行匹配--向项目字典中添加一个项目。我将实际的比对委托给了方法 AddsItem 来保持代码的可读性。

public bool AddsItem(Action<IMappingOperationOptions> providedOptions, string key, object value)
{
    var mappingOptions = new CustomMappingOperationOptions();
    providedOptions.Invoke(mappingOptions);
    return mappingOptions.Items.Any(x => x.Key.Equals(key) && x.Value.Equals(value));
}

基本上比较解析了委托人在做什么,并根据它是否做了我们预期的事情而返回true或false。可以根据需要砍掉和改变比较,我在这里做了一些假设。CustomMappingOperationOptions 只是一个快速的本地实现 IMappingOperationOptions 因为具体的实现看起来有点麻烦,而我们在测试中不需要它。

最后,把它拉到一起。

var mapperMock = new Mock<IMapper>();
mapperMock.Setup(x => x.Map<TransactionDetailsViewModel>(
        transaction,
        It.Is<Action<IMappingOperationOptions>>(opt => AddsItem(opt, nameof(IClockService), new ClockService())))).Returns(viewModel);

var mockedMapper = mapperMock.Object;

var result = mockedMapper.Map<TransactionDetailsViewModel>(transaction, opt => opt.Items.Add(nameof(IClockService), new ClockService()));
© www.soinside.com 2019 - 2024. All rights reserved.