c# - 无法从 System.Reflection.TypeInfo 创建实例
问题描述
我们正在尝试为我们的 ASP.Net Core API 控制器创建一个简单的单元测试。我们将 autofixture 与 autoMoq、XUnit2 和 shoudly 一起使用。我们如何模拟 TypeInfo 的创建?还是有更好的方法?
我们按照这篇文章解决了以下初始错误:
AutoFixture.ObjectCreationException :AutoFixture 无法从 Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary 创建实例,因为创建意外失败并出现异常。请参阅内部异常以调查失败的根本原因。
namespace Tests.Controllers
{
using Api.Controllers;
using AutoFixture;
using AutoFixture.AutoMoq;
using Shouldly;
using System.Threading.Tasks;
using Xunit;
public class DiagnosticControllerTests
{
private readonly DiagnosticController _sut;
public DiagnosticControllerTests()
{
var fixture = new Fixture();
fixture.Customize(new AutoMoqCustomization())
.Customize(new ApiControllerCustomization()); // from Matt Uliasz see link above
_sut = fixture.Create<DiagnosticController>();
}
[Fact]
public async Task Ping_Returns_True()
{
var actual = await _sut.Ping();
actual.Data.ShouldBe(true);
}
}
}
这会引发以下错误:
AutoFixture.ObjectCreationExceptionWithPath AutoFixture 无法从 System.Reflection.TypeInfo 创建实例,因为创建意外失败并出现异常。请参阅内部异常以调查失败的根本原因。...内部异常消息:Castle.DynamicProxy.InvalidProxyConstructorArgumentsException:无法实例化类的代理:System.Reflection.TypeInfo。找不到无参数构造函数。
编辑 经过进一步测试,当我们停止从类 Microsoft.AspNetCore.Mvc.Controller派生时,错误消失了。
namespace Api.Controllers
{
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Models;
using System.Threading.Tasks;
[Authorize]
[Route("api/[controller]")]
public class DiagnosticController: Controller
{
[AllowAnonymous]
[HttpGet]
[Route("ping")]
public Task<PingResultDto> Ping()
{
var result = new PingResultDto
{
Data = true
};
return Task.FromResult(result);
}
}
}
编辑 2 我们目前的解决方法是不使用 AutoFixture/AutoMoq:
var sut = new Mock<DiagnosticController>().Object; //This works
解决方案
尝试这个:
internal class ControllerBaseCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new FilteringSpecimenBuilder(
new Postprocessor(
new MethodInvoker(
new ModestConstructorQuery()),
new ControllerBaseFiller()),
new ControllerBaseSpecification()));
}
private class ControllerBaseFiller : ISpecimenCommand
{
public void Execute(object specimen, ISpecimenContext context)
{
if (specimen == null) throw new ArgumentNullException(nameof(specimen));
if (context == null) throw new ArgumentNullException(nameof(context));
if (specimen is ControllerBase controller)
{
controller.ControllerContext = new ControllerContext
{
HttpContext = (HttpContext)context.Resolve(typeof(HttpContext))
};
}
else
{
throw new ArgumentException("The specimen must be an instance of ControllerBase", nameof(specimen));
}
}
}
private class ControllerBaseSpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request) => request is Type type && typeof(ControllerBase).IsAssignableFrom(type);
}
}
推荐阅读
- swift - 如何使用 SwiftUI 在函数中初始化警报?
- maximo - 从现有路线批量删除路线停靠点?
- javascript - 输入5个数字后返回数组的最大值
- html - 无法在网格容器中均匀地放置项目
- c# - 如何更改在 WorkerService 中搜索 appsettings.json 的位置
- react-native - 在反应原生应用程序的根目录中实现填充的最佳方法是什么?
- google-maps - 我如何限制亚马逊技能的 Google Directions API 访问?
- json - 在 terraform v0.12 中合并字典列表
- mysql - SQL:查找日期之间的差异
- discord.js - Discord.js,JSDOM 无效的 URL