3

我正在使用 Autofac 实现 Xunit,我可以通过以下代码使其工作:

using (var scoped = DbFixture.Container.Resolve<UserReponsitory>())
{
    var result = (scoped.GetAll()).ToList().Count();
    Assert.Equal(2, result);
}

但我想注入 UserReponsitory 来测试方法而不是使用DbFixture.Container.Resolve. 是否可以使下面的代码工作?
单元测试1.cs

namespace XUnitTestPro
{
    public class UnitTest1:IClassFixture<DbFixture>
    {
        private IUserReponsitory _userReponsitory;
        public UnitTest1(IUserReponsitory userReponsitory)
        {
            _userReponsitory = userReponsitory;
        }
        [Fact]
        public void Test1()
        {
            //using (var scoped = DbFixture.Container.Resolve<UserReponsitory>())
            //{
            //    var result = (scoped.GetAll()).ToList().Count();
            //    Assert.Equal(2, result);
            //}
            var result = _userReponsitory.GetAll().ToList().Count();
            Assert.Equal(2, result);
        }
    }
}

DbFixture.cs

namespace XUnitTestPro
{
    public class DbFixture
    {
        public static IContainer Container { get; set; }

        public DbFixture()
        {
            var builder = new ContainerBuilder();
            var option = new DbContextOptionsBuilder<UserContext>().UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=EFProject;Trusted_Connection=True;MultipleActiveResultSets=true").Options;
            UserContext context = new UserContext(option);
            builder.RegisterInstance(context).As<UserContext>();

            builder.RegisterType<UserReponsitory>().AsSelf().As<IUserReponsitory>();

            builder.RegisterAssemblyTypes(typeof(DbFixture).GetTypeInfo().Assembly);

            Container = builder.Build();

        }
    }
}

目前,我得到以下错误,它似乎与IClassFixture<DbFixture>并且public UnitTest1(IUserReponsitory userReponsitory)不同。

消息:以下构造函数参数没有匹配的夹具数据:IUserReponsitory userReponsitory

DbFixture.Container.Resolve有没有什么方法可以在不调用类似于注入 MVC 控制器的情况下实现以下代码?

public UnitTest1(IUserReponsitory userReponsitory)
{
    _userReponsitory = userReponsitory;
}

换句话说,我怎么能依赖注入单元测试类?
任何帮助,将不胜感激。

4

2 回答 2

2

xUnit 中的依赖注入支持有点有限。

当你实现IClassFixture<DbFixture>接口时,xUnit 期望它的构造函数中有一个DbFixture参数,参数的类型取决于Tin IClassFixture<T>

话虽这么说,当您实施时,IClassFixture<DbFixture>您的构造函数必须看起来像public UnitTest1(DbFixture). 但是你有IUserRepository,所以 xUnit 不知道在那里注入什么。

您还可以实现多种IClassFixture<T>类型,但T每个测试类只能使用一次。

来自有关共享上下文( )的官方xUnit 文档IClassFixture<T>

重要提示:xUnit.net 使用接口 IClassFixture<> 的存在来知道您想要创建和清理类固定装置。无论您是否将类的实例作为构造函数参数,它都会这样做。同样,如果您添加了构造函数参数但忘记添加接口,xUnit.net 会告诉您它不知道如何满足构造函数参数。

更新

仍然可以使用 IoC 容器来解决它,只是不能使用构造函数注入。

public class DbFixture
{
    public IContainer Container { get; private set; }

    public DbFixture()
    {
        var builder = new ContainerBuilder();
        var option = new DbContextOptionsBuilder<UserContext>().UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=EFProject;Trusted_Connection=True;MultipleActiveResultSets=true").Options;
        UserContext context = new UserContext(option);
        builder.RegisterInstance(context).As<UserContext>();

        builder.RegisterType<UserReponsitory>().AsSelf().As<IUserReponsitory>();

        builder.RegisterAssemblyTypes(typeof(DbFixture).GetTypeInfo().Assembly);

        Container = builder.Build();
    }
}

public class UnitTest1:IClassFixture<DbFixture>
{
    private IUserReponsitory _userReponsitory;
    public UnitTest1(DbFixture fixture)
    {
        // resolve it here
        _userReponsitory = fixture.Container.Resolve<IUserRepository>();
    }

    [Fact]
    public void Test1()
    {
        //using (var scoped = DbFixture.Container.Resolve<UserReponsitory>())
        //{
        //    var result = (scoped.GetAll()).ToList().Count();
        //    Assert.Equal(2, result);
        //}
        var result = _userReponsitory.GetAll().ToList().Count();
        Assert.Equal(2, result);
    }
}

然而,问题是使用它的好方法是什么?不确定你想要达到什么,但如果你想做单元测试,那么你根本不需要使用 IoC 容器或具体的类,只需模拟和你正在测试的类型。

如果您想在 ASP.NET Core MVC / WebApi 上进行集成测试,那么您应该使用TestServer已在其中配置的所有 IoC 来启动整个应用程序的类。

于 2017-04-21T07:18:46.620 回答
0

如果您已经在单元测试中启用了构造函数注入,那么您就差不多完成了。在测试的构造函数中,注入一个

Func<Owned<UserReponsitory>>

例如

namespace XUnitTestPro
{
public class UnitTest1:IClassFixture<DbFixture>
{
    private Func<Owned<UserReponsitory>> _userRepositoryFactory;
    public UnitTest1(Func<Owned<UserReponsitory>> userRepositoryFactory )
    {
        _userReponsitoryFactory = userReponsitoryFactory;
    }
    [Fact]
    public void Test1()
    {
        //using (var scoped = DbFixture.Container.Resolve<UserReponsitory>())
        //{
        //    var result = (scoped.GetAll()).ToList().Count();
        //    Assert.Equal(2, result);
        //}

        using (var scoped = userReponsitoryFactory())
        {
            var result = (scoped.Value.GetAll()).ToList().Count();
            Assert.Equal(2, result);
        }
    }
}
}

Func 是一个允许您返回 Owned 的工厂。Owned 是一个容器,允许您自行处理对象(使用块)

于 2017-04-20T14:30:10.663 回答