面向云技术架构 - 痴者工良

  • 首页
  • 工良写的电子书
    • kubernetes 教程
    • 从 C# 入门 Kafka
    • 多线程和异步
    • 动态编程-反射、特性、AOP
    • 表达式树
  • 本站文章导航
  • 隐私政策
愿有人陪你颠沛流离
遇到能让你付出的事物或者人,都是一种运气。
能遇到,就该珍惜。或许你们最终没能在一起,但你会切实地感受到力量。
正因为这样,那段相遇才变得有价值,才没有辜负这世间的每一段相遇。
  1. 首页
  2. .NET
  3. 正文

C# 单元测试 Mock 如何获取返回结果

2022年9月26日 736点热度 0人点赞 0条评论
内容纲要

做单元测试的时候往往会使用 Moq 等库,对代码进行 Mock。
但是有些过程,我们希望除了 Mock 方法之外,能够在 Mock 方法中,判断传递的参数是否正确。

因为常规的 Mock ,是返回一个值。

var mock =  new Mock<Test>();
mock.Setup<xxxx>(x => Get)....

var obj = mock.Object;
var result = obj.Get();

在这个时候,是忽略参数和计算过程,返回一个值。

但是我们如果需要一个参数,根据参数判断,是否验证通过。

笔者的需求是,一个数据库同步任务,根据变化的表或数据,生成 SQL ,然后向目标数据库执行 SQL。
因为是单元测试,所以我需要 Mock 数据库,即 Mock SQLCommand 好的 SQLConnect 两个过程。

我做了个接口,进一步解耦数据库连接:


    public class MysqlDatabaseMock : MysqlDatabase
... 
        protected override async Task ExecteAsync(MySqlCommand dbCommand, string sql)
        {
            _output.WriteLine(sql);
            await Task.CompletedTask;
        }
...

这里是个 protected 方法。

可以看到,返回的是 Task,也就是这个方法没有返回值,因此,我们是不能通过获取返回值,判断这个 SQL 是否生成得跟我们的预估一样。我们要做的,就是在 Mock 方法中,执行我们的代码,并且,需要 让 Assert.Equal(left, right); 生效,也就是,我们这个 Assert.Equal 不是放在 Test 方法中,而是放在 Mock 中。

void xxxTest()
{
    mock.Get()
    ... ...
    Get => Assert.Equal() ....
}

实际写法:

        private static void MockExcete(string sqlStr, Mock<MysqlDatabaseMock> mock)
        {
            Func<MySqlConnection, string, Task> func = (connect, sql) =>
            {
                var left = Format(sqlStr);
                var right = Format(sql);
                Assert.Equal(left, right);
                return Task.CompletedTask;
            };
            mock.Protected().Setup<Task>("ExecteAsync", ItExpr.IsAny<MySqlConnection>(), ItExpr.IsAny<string>())
                .Returns((Delegate)func);

            mock.Protected().Setup<Task>("ExecteAsync", ItExpr.IsAny<MySqlCommand>(), ItExpr.IsAny<string>())
                .Returns((Delegate)func);

            static string Format(string sql)
            {
                var newSql = sql
                    .Replace("\r\n", "")
                    .Replace("\r", "")
                    .Replace("\n", "")
                    .Replace(" ", "");
                if (newSql.EndsWith(';'))
                {
                    return newSql[..^1];
                }
                return newSql;
            }
        }

代码很简单,我们使用一个委托,让 Mock 执行这个方法。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: c mock 单元测试 获取 返回
最后更新:2022年9月26日

痴者工良

高级程序员劝退师

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2022 whuanle.cn. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

粤ICP备18051778号

粤公网安备 44030902003257号