我在單元測試項目中使用Moq成功注入了依賴項。但是對於集成測試,我想與數據庫進行交互。所以我會假裝存儲庫/依賴項。我在為集成測試引入的單獨類庫中遇到瞭如何實現這樣的問題。

我想做這樣的事情(數據應該來自數據庫):

public class CountryServiceIntegrationTest
{

    private ICountryService countryService;

    public CountryServiceIntegrationTest(ICountryService _countryService)
    {
        countryService = _countryService;                     
    }

    #endregion


    [Fact]
    public void Should_Return_ListOf_Countries()
    {
        //Act
        var myList = countryService.GetList("A");
        //Assert
        Assert.True(myList.Count > 0);
    }        
}

我的國家服務類:

public class CountryService : ICountryService
{
    // Note: Have to use Core.Domain.Country because of the namespace has Quantum.Service.Country
    protected IRepository<Core.Domain.Country> _countryRepository;
    protected IRepository<Core.Domain.State> _stateRepository;
    protected IRepository<Core.Domain.City> _cityRepository;

    public CountryService(IRepository<Core.Domain.Country> countryRepository, IRepository<Core.Domain.State> stateRepository, IRepository<Core.Domain.City> cityRepository)
    {
        _countryRepository = countryRepository;
        _stateRepository = stateRepository;
        _cityRepository = cityRepository;
    }


    public IList<CountryViewModel> GetList(string name)
    {
        var query = _countryRepository.Table.AsQueryable();
        if (string.IsNullOrEmpty(name) == false)
        {
            query = query.Where(i => i.CountryName.StartsWith(name));
        }
        return query.Select(i => new CountryViewModel()
        {
            CountryCode = i.CountryCode,
            CountryName = i.CountryName,
            Currency = i.Currency,
            CurrencyName = i.CurrencyName,
            CurrencySymbol = i.CurrencySymbol,
            TelephoneCountryCode = i.TelephoneCountryCode,
            UnitOfMeasure = i.UnitOfMeasure
        }).ToList();
    } }

我有單獨的IOC類庫項目,其中註冊了依賴項。然後在Startup.cs類中註冊它。由於在測試期間未調用Startup.cs類,因此不會注入依賴項。那麼我該如何解決這個問題呢?

------更新%的官方文檔中找到指引這裡 -----

那麼現在:我按照這個鏈接按照它做了。在我看來,調用了Startup類,它也調用了ConfigureDependency.RegisterDependencies(..)。

測試類:

    public CountryServiceIntegrationTest()
    {
        _server = new TestServer(new WebHostBuilder()
            .UseStartup<Startup>());
        _client = _server.CreateClient();            
    }

    [Fact]
    public async Task ReturnHelloWorld()
    {
        //Act
        var response = await _client.GetAsync("/home/Test");
        response.EnsureSuccessStatusCode();

        var responseString = await response.Content.ReadAsStringAsync();

        //Assert
        Assert.Equal("test", responseString);
    }

Startup.ConfigureServices():

    public IConfigurationRoot Configuration { get; }

    //gets called in the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {      

        //services.AddSingleton<ILogUserActivityService, LogUserActivityService>();
        services.AddSingleton<ActivityLog>();
        // Add framework services.
        services.AddMvc();
        // Register Database Connection String
        var connectionSetting = new ConnectionSetting(Configuration["Data:ConnectionStrings:DefaultConnection"]);
        services.AddSingleton<IConnectionSetting>(connectionSetting);
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
        // Fill other dependencies
        var configureDependency = new ConfigureDependency();
        configureDependency.RegisterDependencies(services, connectionSetting);          

    }

ConfigureDependency.RegisterDependency(..):

 public class ConfigureDependency
{
    public IDatabaseFactory DatabaseFactory { get; set; }
    public void RegisterDependencies(IServiceCollection services, IConnectionSetting connectionSetting)
    {

        services.AddDbContext<QuantumDbContext>(options => options.UseSqlServer(connectionSetting.Get()));

        services.AddTransient<IDatabaseFactory, DatabaseFactory>();
        services.AddTransient<IDbContext, TestDbContext>();
        services.AddTransient<IDbContext, QuantumDbContext>();

        ..................................................................
        ...........service n repositories  are registered here..............

  }
}

但現在發生的是我收到此錯誤: 在此處輸入圖像描述

由於調用Startup.cs然後調用ConfigureDependency類,這並不意味著應自動傳遞參數(services,connectionSetting)。這是(ConfigureDependency.RegisterDependencies(..))我收到錯誤。

熱門答案

這是useSqlServer方法中的ArgumentNullException

似乎connectionSetting.Get()返回null

在以下代碼中

var connectionSetting = new ConnectionSetting(Configuration["Data:ConnectionStrings:DefaultConnection"]);
services.AddSingleton<IConnectionSetting>(connectionSetting);

它建議ConnectionSetting實現接口IConnectionSetting ,那你為什麼不直接使用實例而不是調用Get()呢?

如下所示:

services.AddDbContext<QuantumDbContext>(options => options.UseSqlServer(connectionSetting))

補充說明:
這實際上取決於你通過集成測試的意思。它可以指:

  • 更高級別的單元測試 (相對於僅限於一個類的單元測試,這種集成測試將測試不同類之間的集成)。
  • 命名空間級別集成測試 (測試來自給定命名空間的一個或多個公共接口,而不檢查內部類)。
  • 程序集級集成測試 (與命名空間相同但具有程序集範圍)。
  • 黑盒集成測試 (從外部系統的角度測試完整軟件的交互)。 ASP.NET集成測試文檔與此類測試有關。

在嘗試進行大爆炸測試之前,通常可以更好地測試幾層測試 ......但這需要在時間和質量之間進行權衡

為了使不那麼高級別的集成測試成為可能/易於編寫:

  • 您不應在測試和生產代碼之間共享相同的數據庫環境 (因此不是相同的連接字符串)。

  • 你不應該使用Startup,因為它的目的是模仿測試服務器上的整個網站。

  • 服務的註冊和解決應該分成一些連貫的特定類,以便更容易地對特定部分進行集成測試。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因