我在單元測試項目中使用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))
補充說明:
這實際上取決於你通過集成測試的意思。它可以指:
在嘗試進行大爆炸測試之前,通常可以更好地測試幾層測試 ......但這需要在時間和質量之間進行權衡 。
為了使不那麼高級別的集成測試成為可能/易於編寫:
您不應在測試和生產代碼之間共享相同的數據庫環境 (因此不是相同的連接字符串)。
你不應該使用Startup,因為它的目的是模仿測試服務器上的整個網站。
服務的註冊和解決應該分成一些連貫的特定類,以便更容易地對特定部分進行集成測試。