如何使用xUnit为服务层编写测试?

时间:2016-12-01 03:46:33

标签: unit-testing asp.net-core xunit in-memory-database service-layer

如何使用xUnit为服务层编写测试?我正在为我的服务层使用依赖注入,但是如何在内存数据库中使用它来创建它的实例呢?这是我到目前为止所做的,我遵循这个link,这就是我使用我的服务层,但它是一个烂摊子,我不知道如何简化它。我在所有控制器中使用服务接口

    [Fact]
    public void Add_writes_to_database()
    {
        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseInMemoryDatabase(databaseName: "Add_writes_to_database")
            .Options;

        // Run the test against one instance of the context
        using (var context = new ApplicationDbContext(options))
        {
            var productRepo = new Repository<Product>(context);
            var categoryRepo = new Repository<Category>(context);
            var categoryMappingRepo = new Repository<ProductCategoryMapping>(context);
            var categoryService = new CategoryService(context, categoryRepo, categoryMappingRepo);
            var manufacturerRepo = new Repository<Manufacturer>(context);
            var manufacturerMappingRepo = new Repository<ProductManufacturerMapping>(context);
            var manufacturerService = new ManufacturerService(context, manufacturerRepo, manufacturerMappingRepo);
            var imageRepo = new Repository<Image>(context);
            var imageMappingRepo = new Repository<ProductImageMapping>(context);
            var imageService = new ImageManagerService(imageRepo, imageMappingRepo);
            var specificationRepo = new Repository<Specification>(context);
            var specificationMappingRepo = new Repository<ProductSpecificationMapping>(context);
            var specificationService = new SpecificationService(context, specificationRepo, specificationMappingRepo);
            var productService = new ProductService(context, productRepo, categoryService, manufacturerService, imageService, specificationService);

            var product = new Product() { Id = Guid.NewGuid(), Name = "Product1", Price = 100m };

            productService.InsertProduct(product);
        }

        // Use a separate instance of the context to verify correct data was saved to database
        using (var context = new ApplicationDbContext(options))
        {
            var productRepo = new Repository<Product>(context);
            var categoryRepo = new Repository<Category>(context);
            var categoryMappingRepo = new Repository<ProductCategoryMapping>(context);
            var categoryService = new CategoryService(context, categoryRepo, categoryMappingRepo);
            var manufacturerRepo = new Repository<Manufacturer>(context);
            var manufacturerMappingRepo = new Repository<ProductManufacturerMapping>(context);
            var manufacturerService = new ManufacturerService(context, manufacturerRepo, manufacturerMappingRepo);
            var imageRepo = new Repository<Image>(context);
            var imageMappingRepo = new Repository<ProductImageMapping>(context);
            var imageService = new ImageManagerService(imageRepo, imageMappingRepo);
            var specificationRepo = new Repository<Specification>(context);
            var specificationMappingRepo = new Repository<ProductSpecificationMapping>(context);
            var specificationService = new SpecificationService(context, specificationRepo, specificationMappingRepo);
            var productService = new ProductService(context, productRepo, categoryService, manufacturerService, imageService, specificationService);

            Assert.Equal(1, productService.GetAllProduct().Count());
        }
    }

我的productService对其他服务,存储库和上下文有很多依赖。

1 个答案:

答案 0 :(得分:1)

是的,你有很多依赖服务和存储库。由于您已经为服务使用了依赖注入,我建议您使用IoC容器。这不仅会删除大量代码来设置集成测试,还可以帮助您轻松解决应用程序中的任何服务。

你可以为你的类型映射创建一个类:

public class Services
{
    private readonly DbContextOptions _options;
    private readonly IUnityContainer _container;

    public Services(DbContextOptions options)
    {
        _options = options;
        _container = new UnityContainer();
        RegisterTypes();
    }

    private void RegisterTypes()
    {
        _container.RegisterType<IApplicationDbContext, ApplicationDbContext>(new ContainerControlledLifetimeManager(), new InjectionConstructor(_options));
        _container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
        _container.RegisterType<ISpecificationService, SpecificationService>(new ContainerControlledLifetimeManager());
        _container.RegisterType<IImageManagerService, ImageManagerService>(new ContainerControlledLifetimeManager());
        _container.RegisterType<IRepository<ProductSpecificationMapping>, Repository<ProductSpecificationMapping>>(new ContainerControlledLifetimeManager());
        // etc ...
    }

    public T Get<T>()
    {
        return _container.Resolve<T>();
    }
}

然后,您可以最小化解决产品服务所需的测试代码:

[Fact]
public void Add_writes_to_database()
{
    var options = new DbContextOptionsBuilder<ApplicationDbContext>()
        .UseInMemoryDatabase(databaseName: "Add_writes_to_database")
        .Options;

    var services = new Services(options);
    var target = services.Get<IProductService>();

    // to your testing
}

我还没有在VS中测试和验证这些代码行,但它应该会给你一个想法。我们在我们的应用程序中也使用了这种方法,您可以使用自己喜欢的IoC容器。您还需要存储库和服务的接口,但最好还是使用它们: - )