【问题标题】:Unable to create an instance from System.Reflection.TypeInfo无法从 System.Reflection.TypeInfo 创建实例
【发布时间】:2019-07-15 14:10:23
【问题描述】:

我们正在尝试为我们的 ASP.Net Core API 控制器创建一个简单的单元测试。我们将 autofixture 与 autoMoq、XUnit2 和 shoudly 一起使用。我们如何模拟 TypeInfo 的创建?还是有更好的方法?

我们关注this post解决了最初的错误:

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

【问题讨论】:

  • 你确定这些类有一个无参数的构造函数:Could not find a parameterless constructor,因为其中一个没有......如果你把AutoMoqCustomizationApiControllerCustomization拉出来,你能创建它们的实例吗?
  • 您是否要模拟TypeInfo 对象本身?或者您是否正在尝试创建一个类型由TypeInfo描述 的模拟对象?当你真的想要后者时,听起来你正在尝试做前者。您不应该实例化或模拟新的 TypeInfo 对象。您需要显示更多代码。

标签: c# unit-testing autofixture automoq


【解决方案1】:

试试这个:

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);
    }
}

【讨论】:

    【解决方案2】:

    请注意,我在下面的回答并没有真正解决您的问题,但这更像是一个提示:

    我认为你的测试过于复杂了。

    请记住,单元测试是为核心业务逻辑保留的。

    对于端到端测试,应该进行集成测试。

    如果您想进行集成测试,请使用以下命令: https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2

    如果你真的想测试你的控制器: https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/testing?view=aspnetcore-2.2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-04
      • 1970-01-01
      • 2020-01-16
      • 2019-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多