【问题标题】:MOQ IConfiguration with specific parametersMOQ IConfiguration 与特定参数
【发布时间】:2019-09-24 22:07:20
【问题描述】:

今天我正在为我的一个类编写一个单元测试,该类在构造函数中具有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 类?

更新:

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

【问题讨论】:

  • 您是否将模拟配置为在调用时按预期运行?
  • @Nkosi,是的,我在任何其他代码生成器之前都有这一行 = new Fixture().Customize(new AutoMoqCustomization());
  • 所做的只是创建一个模拟。它在配置 mock 的行为方面没有任何作用
  • @Nkosi,你的意思是这样的配置["API:Key"] = "testKey"; ?您能否提供一个配置模拟行为的示例,因为我想我不确定您在说什么?
  • 显示正在测试的主题类和目前的测试

标签: c# unit-testing .net-core mstest autofixture


【解决方案1】:

所做的只是创建一个模拟。它在配置 mock 的行为方面没有任何作用。

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

解决与其原始设计相关的问题。

【讨论】:

  • 这很奇怪,但我仍然找不到 API 密钥。它对你有用吗?
  • 我发布的代码是我用来测试的实际代码,它有效。这就是我能够找到您的堆栈溢出错误和 URL 错误的方式
  • 是的。有用。对困惑感到抱歉。 Visual Studio 无法正常工作。现在一切正常。谢谢!
猜你喜欢
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-10
  • 2021-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多