1

서비스 레이어에 xUnit을 사용하여 테스트를 작성하는 방법은 무엇입니까? 내 서비스 계층에 대한 의존성 삽입을 사용하고 있지만 메모리 데이터베이스에서 인스턴스를 만들 수 있습니까? 여기에 내가 지금까지 가지고있는 것은 무엇입니까, 나는이 link을 따르며, 여기에 내 서비스 계층을 사용하기 위해 나온 것이지만 그것은 혼란이었고 그것을 단순화하는 방법을 알지 못합니다. 임 내 컨트롤러 서비스 레이어에 xUnit을 사용하여 테스트를 작성하는 방법은 무엇입니까?

[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

예, 많은 의존 서비스와 저장소가 있습니다. 이미 서비스에 Dependency Injection을 사용하고 있으므로 IoC 컨테이너를 사용하는 것이 좋습니다. 이렇게하면 통합 테스트를 설정하기위한 많은 코드가 제거 될뿐 아니라 응용 프로그램의 모든 서비스를 쉽게 해결할 수 있습니다.

당신이처럼 형식 매핑을위한 클래스를 만들 수

:

[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 
} 

:

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

그런 다음 당신이 제품 서비스를 해결하는 데 필요한 테스트의 코드를 최소화 할 수 있습니다를 VS에서이 코드 라인을 테스트하고 검증하지는 않았지만 아이디어를 제공해야합니다. 우리는 응용 프로그램 중 하나에서 Unity와이 접근 방식을 사용하고 있으며, 여러분이 좋아하는 IoC 컨테이너를 사용할 수 있습니다. 당신은 또한 귀하의 저장소 및 서비스에 대한 인터페이스가 필요하지만, 어쨌든 그들을 가지고 더 좋습니다 :-)

+0

어떤 생각이 내가 어떻게 할 수있는 기본 asp.net 코어 의존성 주입을 사용합니까? – kram005