我有一个API,我打算在其上通过xUnit和Moq进行单元测试.它实际上有一个构造函数,但我不得不添加另一个构造函数,以根据Visual Studio的建议进行特定的测试.它非常适合测试,但在try 通过Swagger测试API时,我遇到了另一个错误. "System.InvalidOperationException: Multiple constructors accepting all given argument types have been found in type 'Product.API.Controllers.ProductController'. There should only be one applicable constructor". 下面是控制器的内容

public class ProductController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly IConfiguration _configuration;
    private readonly UserManager<User> _userManager;
    private readonly SignInManager<User> _signInManager;
    private readonly ProductDbContext _productDbContext;
    private readonly IUserService _userService;

    public ProductController(IConfiguration configuration, UserManager<User> userManager, ProductDbContext productDbContext
        , SignInManager<User> signInManager, IUserService userService)
    {
        _configuration = configuration;
        _userManager = userManager;
        _productDbContext = productDbContext;
        _signInManager = signInManager;
        _userService = userService;
    }
    public ProductController(IMediator mediator)
    {
        _mediator = mediator;
    }
    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> GetAllProducts()
    {
        var products = await _mediator.Send(new GetAllProductsQuery());
        return Ok(products);
    }

以下是单元测试的代码

private readonly Mock<IMediator> _mediatorMock;
private readonly ProductController _controller;
public ProductControllerTest()
{
    _mediatorMock = new Mock<IMediator>();
    _controller = new ProductController(_mediatorMock.Object);
}
[Fact]
public async Task ProductController_GetAllProducts_ShouldReturnStatusCode200()
{
    //arrange
    var expected = new List<ProductModelDTO>();
    _mediatorMock.Setup(m=> m.Send(It.IsAny<GetAllProductsQuery>(), default(CancellationToken))).ReturnsAsync(expected);
    //act
    var result = await _controller.GetAllProducts();
    //assert
    var okResult = result as OkObjectResult;
    okResult?.StatusCode.Should().Be(200);
    okResult?.Value.Should().BeOfType<List<ProductModelDTO>>();
}

我遇到了一个可能的解决方案;向第二个构造函数添加一个[FromServices].但我也犯了同样的错误!

推荐答案

将所有依赖项移动到单个ctor:

public ProductController(IConfiguration configuration, 
    UserManager<User> userManager, 
    ProductDbContext productDbContext, 
    SignInManager<User> signInManager, 
    IUserService userService, 
    IMediator mediator)
{
    // ...
}

然后在测试中将所有值传递给它:

public ProductControllerTest()
{
    _mediatorMock = new Mock<IMediator>();
    // mock and pass everything:
    _controller = new ProductController(..., _mediatorMock.Object); 
}

或者,您可以使用ASP.NET核心功能来使用方法注入(Action injection with FromServices),尽管您仍然需要将所有公共参数传递给ProductController ctor,但您可以减少它们的总数,并仅在需要它们的地方管理非共享参数:

public ProductController(IConfiguration configuration, UserManager<User> userManager, ProductDbContext productDbContext
    , SignInManager<User> signInManager, IUserService userService)
{
    _configuration = configuration;
    _userManager = userManager;
    _productDbContext = productDbContext;
    _signInManager = signInManager;
    _userService = userService;
}

[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> GetAllProducts([FromServices] IMediator mediator)
{
    var products = await _mediator.Send(new GetAllProductsQuery());
    return Ok(products);
}

请注意,在一般情况下,同时注入IMediator和诸如数据库上下文和单独的服务之类的东西,并且看起来像是一种气味,常见的方法是要么使用IMediator来(几乎)所有的东西,如果使用它的话.

Csharp相关问答推荐

如何使用PDFSharp将文本添加到现有PDF

使用ElasticsearchClient设置忽略属性.默认MappingFor<>

在包含空项的列表上使用具有断言T的摘要表

无法将blob发送到Azure -缺少HTTP标头异常

Blazor:计算值或保留为默认值

为什么我的ASP.NET核心MVC应用程序要为HTML元素添加一些标识符?

(乌龙)1&#比c#中的UL&#慢吗?

在实体框架中处理通用实体&S变更跟踪器

TeamsBot SendActivityActivityTypes与ActivityTypes同步.键入不再起作用

反序列化私有成员

用C#从XML内部元素中获取特定值

是否可以在Entity Framework Core中使用只读 struct 作为拥有实体?

此异步方法在重写方法中缺少等待运算符警告

EF Core 7-忽略模型绑定中的虚拟属性

如何在使用Google.Drive.apis.V3下载文件/文件夹之前压缩?

如何使用.NET 8.0中新的CompositeFormat类?

在使用.NET EF Core DbContext属性之前,是否应使用null判断

如果所有";async任务方法()";调用都返回Task.FromResult()-是否同步执行?

客户端/服务器RPC如何处理全局变量?

为什么我的UserControl没有加载到我的主窗口中?