XUnit 测试错误:测试类只能定义一个公共构造函数

ama*_*ame 8 c# api unit-testing xunit visual-studio

我有一个 XUnit 项目,它引用并测试另一个项目的 API 端点方法。但是,当我运行测试时,出现以下错误:

A test class may only define a single public constructor.
Run Code Online (Sandbox Code Playgroud)

还没有找到太多关于这个问题可能意味着什么的信息,但我将提供下面的代码示例。任何帮助是极大的赞赏。

APIControllerTest.cs

using System;
using System.Collections.Generic;
using AppointmentAPI.Controllers;
using AppointmentAPI.Appt_Models;
using Microsoft.EntityFrameworkCore;
using Xunit;

namespace AppointmentAPITests
{
    public class APIControllerTests
    {

        #region Seeding
        protected APIControllerTests(DbContextOptions<ApptSystemContext> contextOptions)
        {
            ContextOptions = contextOptions;

            Seed();
        }

        protected DbContextOptions<ApptSystemContext> ContextOptions { get; }

        private void Seed()
        {
            using (var context = new ApptSystemContext(ContextOptions))
            {
                // this ensures that a fresh in-memory db is used for each test
                context.Database.EnsureDeleted();
                context.Database.EnsureCreated();

                var one = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 1,
                    Date = Convert.ToDateTime("2020-03-31 00:00:00.000"),
                    Time = TimeSpan.Parse("12:00:00.0000000"),
                    ApptJson = "{'fname':'Billy','lname':'Joel','age':70,'caseWorker':'Donna', 'appStatus':'finished'}",
                    Timestamp = Convert.ToDateTime("2020-02-24 12:00:00.000")
                });

                var two = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 2,
                    Date = Convert.ToDateTime("2020-02-14 00:00:00.000"),
                    Time = TimeSpan.Parse("10:30:00.0000000"),
                    ApptJson = "{'fname':'Nick','lname':'Nicholas','age':25,'caseWorker':'Brenda', 'appStatus':'finished'}",
                    Timestamp = Convert.ToDateTime("2020-02-10 11:38:00.000")
                });

                var three = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 3,
                    Date = Convert.ToDateTime("2020-01-02 00:00:00.000"),
                    Time = TimeSpan.Parse("03:45:00.0000000"),
                    ApptJson = "{'fname':'Macey','lname':'Johnson','age':43,'caseWorker':'Donna', 'appStatus':'unfinished'}",
                    Timestamp = Convert.ToDateTime("2020-01-01 09:34:00.000")
                });

                var four = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 4,
                    Date = Convert.ToDateTime("2020-05-17 00:00:00.000"),
                    Time = TimeSpan.Parse("01:15:00.0000000"),
                    ApptJson = "{'fname':'James','lname':'Wally','age':35,'caseWorker':'Brad', 'appStatus':'finished'}",
                    Timestamp = Convert.ToDateTime("2020-04-28 02:03:00.000")
                });

                var five = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 5,
                    Date = Convert.ToDateTime("2019-11-23 00:00:00.000"),
                    Time = TimeSpan.Parse("12:45:00.0000000"),
                    ApptJson = "{'fname':'Emily','lname':'Carlton','age':62,'caseWorker':'Brenda', 'appStatus':'unfinished'}",
                    Timestamp = Convert.ToDateTime("2019-11-19 11:07:00.000")
                });

                var six = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 6,
                    Date = Convert.ToDateTime("2020-07-24 00:00:00.000"),
                    Time = TimeSpan.Parse("10:00:00.0000000"),
                    ApptJson = "{'fname':'Michael','lname':'Smith','age':52,'caseWorker':'Donna', 'appStatus':'finished'}",
                    Timestamp = Convert.ToDateTime("2020-06-25 09:34:00.000")
                });

                var seven = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 7,
                    Date = Convert.ToDateTime("2020-05-19 00:00:00.000"),
                    Time = TimeSpan.Parse("08:45:00.0000000"),
                    ApptJson = null,
                    Timestamp = null
                });

                var eight = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 8,
                    Date = Convert.ToDateTime("2020-06-05 00:00:00.000"),
                    Time = TimeSpan.Parse("02:45:00.0000000"),
                    ApptJson = null,
                    Timestamp = null
                });

                var nine = context.AppointmentSlots.Add(new AppointmentSlots
                {
                    SlotId = 9,
                    Date = DateTime.Now.AddMonths(2),
                    Time = TimeSpan.Parse("02:45:00.0000000"),
                    ApptJson = null,
                    Timestamp = null
                });

                context.AddRange(one, two, three, four, five, six, seven, eight, nine);

                context.SaveChanges();
            }
        }
        #endregion

        #region AssignAppts
        [Fact]
        public void TestAssignAppts()
        {
            using (var context = new ApptSystemContext(ContextOptions))
            {
                var controller = new apptController(context);

                // Arrange
                var request = new AppointmentAPI.Appt_Models.AppointmentSlots
                {
                    SlotId = 7,
                    ApptJson = "{'fname':'Emily','lname':'Carlton','age':62,'caseWorker':'Brenda', 'appStatus':'unfinished'}",
                    Timestamp = Convert.ToDateTime("2020-06-25 09:34:00.000")
                };

                string expectedResponse = "Task Executed\n";

                // Act
                var response = controller.assignAppt(request);

                // Assert
                Assert.Equal(response, expectedResponse);
            }
        }
        #endregion
    }
}

Run Code Online (Sandbox Code Playgroud)

sqliteInMemoryAPIController.cs

using System;
using System.Collections.Generic;
using System.Data.Common;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using AppointmentAPI.Appt_Models;

namespace AppointmentAPITests
{
    #region SqliteInMemory
    class SqliteInMemoryAPIController : APIControllerTests, IDisposable
    {
        private readonly DbConnection _connection;

        private SqliteInMemoryAPIController()
            : base(
                 new DbContextOptionsBuilder<ApptSystemContext>()
                     .UseSqlite(CreateInMemoryDatabase())
                     .Options)
        {
            _connection = RelationalOptionsExtension.Extract(ContextOptions).Connection;

        }

        private static DbConnection CreateInMemoryDatabase()
        {
            var connection = new SqliteConnection("Filename:=memory:");

            connection.Open();

            return connection;
        }

        public void Dispose() => _connection.Dispose();
    }
    #endregion
}

Run Code Online (Sandbox Code Playgroud)

Bou*_*egh 17

构造函数必须是public,它protected在您的示例中:

public APIControllerTests(DbContextOptions<ApptSystemContext> contextOptions)
{
    ContextOptions = contextOptions;
    
    Seed();
}
Run Code Online (Sandbox Code Playgroud)


小智 2

在搜索相同的答案后我发现了你的问题。

看起来您也在遵循本指南:https://github.com/dotnet/EntityFramework.Docs/blob/master/samples/core/Miscellaneous/Testing/ItemsWebApi/Tests/ItemsControllerTest.cs

public class APIControllerTests
Run Code Online (Sandbox Code Playgroud)

应该是

public abstract class APIControllerTests
Run Code Online (Sandbox Code Playgroud)

  • 在我的例子中,使类抽象并不能解决这个问题。当类是抽象类时,其中的测试不会显示在测试资源管理器中。 (2认同)