最小起订量 IConfiguration 具有特定参数
MOQ IConfiguration with specific parameters
今天我正在为我的一个 class 编写单元测试,它在构造函数中有一个参数 IConfiguration。我试图冻结依赖并创建 sut。
configuration = builders.Freeze<IConfiguration>();
apiConfiguration = builders.Create<IAPIConfiguration>();
当我 运行 测试时出现异常,因为在 API 配置构造函数中我有验证行。
this.API_KEY = configuration["API:Key"] ?? throw new NoNullAllowedException("API key wasn't found.");
它似乎没有以正确的方式或至少是我想要的方式进行模拟。
我开始怀疑是否有任何方法可以使用可自定义的键来模拟 IConfiguration class?
更新:
SUT:
public class APIConfiguration : IAPIConfiguration
{
public APIConfiguration(IConfiguration configuration)
{
this.API_KEY = configuration["API:Key"] ?? throw new NoNullAllowedException("API key wasn't found.");
this._url = configuration["API:URL"] ?? throw new NoNullAllowedException("API key wasn't found.");
}
public string API_KEY { get; }
private string _url
{
get { return this._url; }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new NoNullAllowedException("API url wasn't found.");
this._url = value;
}
}
public Uri URL
{
get
{
return this.URL;
}
private set
{
value = new Uri(this._url);
}
}
}
到目前为止的测试用例:
[TestClass]
public class UnitTest1
{
private readonly IFixture builders;
private readonly string _apiKey;
private readonly string _url;
private readonly IAPIConfiguration apiConfiguration;
private readonly IConfiguration configuration;
public UnitTest1()
{
builders = new Fixture().Customize(new AutoMoqCustomization());
_apiKey = builders.Create<string>();
_url = builders.Create<string>();
configuration = builders.Freeze<IConfiguration>();
configuration["API:Key"] = "testKey";
configuration["API:URL"] = "testUrl";
apiConfiguration = builders.Build<IAPIConfiguration>().Create();
}
[TestMethod]
public void TestMethod1()
{
Assert.AreSame(configuration["API:Key"], apiConfiguration.API_KEY);
}
}
在线测试的构造函数中测试刹车
apiConfiguration = builders.Build<IAPIConfiguration>().Create();
所做的只是创建一个模拟。它对配置模拟的行为没有任何作用。
[TestMethod]
public void TestMethod1() {
//Arrange
//Freeze-Build-Create sequence
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var apiKey = fixture.Create<string>();
var url = "http://example.com";
var configuration = fixture.Freeze<IConfiguration>();
//Configure the expected behavior of the mock
var keys = new Dictionary<string, string> {
{ "API:Key" , apiKey },
{ "API:URL", url }
};
var mock = Mock.Get(configuration);
mock.Setup(_ => _[It.IsAny<string>()]).Returns((string key) => keys[key]);
IAPIConfiguration apiConfiguration = fixture.Build<APIConfiguration>().Create();
//Act
var actual = apiConfiguration.API_KEY;
//Assert
Assert.AreEqual(apiKey, actual);
Assert.AreEqual(new Uri(url), apiConfiguration.URL);
}
以上从 fixture 中提取 mock 并配置测试用例的预期行为。
该测试还暴露了被测对象的问题,这些问题必须重构为
public class APIConfiguration : IAPIConfiguration {
public APIConfiguration(IConfiguration configuration) {
this.API_KEY = configuration["API:Key"] ?? throw new NoNullAllowedException("API key wasn't found.");
this._url = configuration["API:URL"] ?? throw new NoNullAllowedException("API url wasn't found.");
}
public string API_KEY { get; }
private string _url;
public Uri URL {
get {
return new Uri(this._url);
}
}
}
修复与其原始设计相关的问题。
今天我正在为我的一个 class 编写单元测试,它在构造函数中有一个参数 IConfiguration。我试图冻结依赖并创建 sut。
configuration = builders.Freeze<IConfiguration>();
apiConfiguration = builders.Create<IAPIConfiguration>();
当我 运行 测试时出现异常,因为在 API 配置构造函数中我有验证行。
this.API_KEY = configuration["API:Key"] ?? throw new NoNullAllowedException("API key wasn't found.");
它似乎没有以正确的方式或至少是我想要的方式进行模拟。 我开始怀疑是否有任何方法可以使用可自定义的键来模拟 IConfiguration class?
更新:
SUT:
public class APIConfiguration : IAPIConfiguration
{
public APIConfiguration(IConfiguration configuration)
{
this.API_KEY = configuration["API:Key"] ?? throw new NoNullAllowedException("API key wasn't found.");
this._url = configuration["API:URL"] ?? throw new NoNullAllowedException("API key wasn't found.");
}
public string API_KEY { get; }
private string _url
{
get { return this._url; }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new NoNullAllowedException("API url wasn't found.");
this._url = value;
}
}
public Uri URL
{
get
{
return this.URL;
}
private set
{
value = new Uri(this._url);
}
}
}
到目前为止的测试用例:
[TestClass]
public class UnitTest1
{
private readonly IFixture builders;
private readonly string _apiKey;
private readonly string _url;
private readonly IAPIConfiguration apiConfiguration;
private readonly IConfiguration configuration;
public UnitTest1()
{
builders = new Fixture().Customize(new AutoMoqCustomization());
_apiKey = builders.Create<string>();
_url = builders.Create<string>();
configuration = builders.Freeze<IConfiguration>();
configuration["API:Key"] = "testKey";
configuration["API:URL"] = "testUrl";
apiConfiguration = builders.Build<IAPIConfiguration>().Create();
}
[TestMethod]
public void TestMethod1()
{
Assert.AreSame(configuration["API:Key"], apiConfiguration.API_KEY);
}
}
在线测试的构造函数中测试刹车
apiConfiguration = builders.Build<IAPIConfiguration>().Create();
所做的只是创建一个模拟。它对配置模拟的行为没有任何作用。
[TestMethod]
public void TestMethod1() {
//Arrange
//Freeze-Build-Create sequence
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var apiKey = fixture.Create<string>();
var url = "http://example.com";
var configuration = fixture.Freeze<IConfiguration>();
//Configure the expected behavior of the mock
var keys = new Dictionary<string, string> {
{ "API:Key" , apiKey },
{ "API:URL", url }
};
var mock = Mock.Get(configuration);
mock.Setup(_ => _[It.IsAny<string>()]).Returns((string key) => keys[key]);
IAPIConfiguration apiConfiguration = fixture.Build<APIConfiguration>().Create();
//Act
var actual = apiConfiguration.API_KEY;
//Assert
Assert.AreEqual(apiKey, actual);
Assert.AreEqual(new Uri(url), apiConfiguration.URL);
}
以上从 fixture 中提取 mock 并配置测试用例的预期行为。
该测试还暴露了被测对象的问题,这些问题必须重构为
public class APIConfiguration : IAPIConfiguration {
public APIConfiguration(IConfiguration configuration) {
this.API_KEY = configuration["API:Key"] ?? throw new NoNullAllowedException("API key wasn't found.");
this._url = configuration["API:URL"] ?? throw new NoNullAllowedException("API url wasn't found.");
}
public string API_KEY { get; }
private string _url;
public Uri URL {
get {
return new Uri(this._url);
}
}
}
修复与其原始设计相关的问题。