【问题标题】:C# moq how to correctly setup an interface to return a desired valueC# moq 如何正确设置接口以返回所需值
【发布时间】:2021-06-28 05:11:46
【问题描述】:

我已经为我的应用编写了各种测试,但现在我遇到了一个我无法解决的问题。 我正在编写的测试是一个简单的命令,它执行和修改数据库的操作,然后是一个查询以验证值是否正确。 为了连接到数据库,我的 BaseContext 从接口获取连接字符串:

        public BaseContext(DbContextOptions options, IConnectionStringProvider connectionStringProvider)
            : base(options)
        {
            _connectionStringProvider   = connectionStringProvider;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                var connString =_connectionStringProvider.GetConnectionString();
                optionsBuilder.UseOracle(connString);
            }
        }

我的连接字符串提供程序界面如下所示:

    public interface IConnectionStringProvider
    {
        string GetConnectionString();
        Dictionary<string, string> GetConnectionSession();
    }

实现如下所示:


    public class HttpConnectionStringProvider : IConnectionStringProvider
    {
        public HttpConnectionStringProvider(IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
        {
            _configuration = configuration ?? throw new NullReferenceException(nameof(configuration));
            _httpContext = httpContextAccessor.HttpContext ?? throw new NullReferenceException("HttpContext");
        }

        public string GetConnectionString()
        {
            // Do something with http context and configuration file and return connection string
        }

    }

所有这些接口都是使用 autofac 注册的。

然后在执行以下测试时:


        [Test]
        public async Task AddProductTest()
        {

            string connectionString = "fixed_connection_string";

            var mock = new MockRepository(MockBehavior.Default);

            var mockConnectionStringProvider = new Mock<IConnectionStringProvider>();
            mockConnectionStringProvider.Setup(x => x.GetConnectionString())
                .Returns(connectionString);


            await ProductModule.ExecuteCommandAsync(new AddProductCommand(1, "nameProduct"));

            var products = await ProdcutModule.ExecuteQueryAsync(new GetProducts(1));
            // Assert
            Assert.That(products .Status, Is.EqualTo(ResultQueryStatus.Ok));
            Assert.That(products .Value, Is.Not.Empty);
            Assert.That(products .Value.Any(x => x.Name== "nameProduct"));
        }

使用 NSubstitute 库模拟 IConfiguration 和 IHttpContextAccessor。但即使我删除它们只是为了测试 IConnectionStringProvider 是否返回了设置中预期的值,它也不起作用。

在调试中运行测试时,我看到应该模拟 GetConnectionString() 方法的步骤。我不知道我做错了什么我想我对测试有些不理解。

【问题讨论】:

  • 您创建mockConnectionStringProvider。您实际在哪里使用它?
  • 命令 AddProduct 被分派时执行的命令处理程序使用 ProductRepository,而 ProductRepository 又使用使用 ConnectionStringProvider 的 BaseContext。还是您的意思是我必须将 mockConnectionStringProvider 实际传递给使用它的实际对象?那如果是使用依赖注入注册的怎么办呢?
  • 在测试中,您应该模拟依赖项并将模拟依赖项注册或注入实际依赖项,以便使用这些依赖项的类将引用模拟。您的设计应遵循 SOLID 原则,这将使您的代码具有可测试性和可扩展性。

标签: c# unit-testing dependency-injection moq


【解决方案1】:

我很好奇你想做什么:

模拟数据库连接字符串或类似的创建某人的连接字符串没有多大意义。它是安装程序中用于 C# 服务处理的 DI 位的基本功能的一部分。

如果你想搞砸这个,当然可以,但目的有点逃跑了。

但是,如果您只是想将 ProductModule 测试为您编写的内容,那么它更有意义。

那么当你做出这样的声明时:

ProductModule productModule = new ProductModule( - 参数 - ); 您的参数可能需要 IConnectionStringProvider。

你需要使用你的 mockConnectionStringProvider.Object

这将允许您插入模拟对象,作为 ProductModule 构造函数中使用的对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多