首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用moq对存储库和模拟数据库进行单元测试

如何使用moq对存储库和模拟数据库进行单元测试
EN

Stack Overflow用户
提问于 2020-04-28 22:22:01
回答 1查看 119关注 0票数 0

我一个人在一个没有任何单元测试的现有项目中工作。在进行任何重构之前,我的第一个目标是覆盖100%的代码。我希望避免任何倒退。

我已经读过how do I mock sqlconnection or should I refactor the code?了,但是我的情况很不一样,因为我需要做的不仅仅是存根,简单地说就是sqlConnection。基本上,我需要模拟数据库。我想知道实现它的最佳方法。

(顺便说一下,我不想使用任何ORM,比如Entity)。下面是存储库的代码:

代码语言:javascript
复制
public class HotelRepository : IHotelRepository
{
    private readonly IDbConnection _dbConnection;
    private readonly ILogService _loggerService;

    public HotelRepository(IDbConnection dbConnection, ILogService loggerService)
    {
        _dbConnection = dbConnection;
        _loggerService = loggerService;
    }

    public HotelDo GetByRid(string rid)
    {
        return Find(rid).FirstOrDefault();
    }

    public List<HotelDo> Find(string text)
    {
        try
        {
            _dbConnection.Open();

            var items = new List<HotelDo>();
            using (var command = _dbConnection.CreateCommand())
            {
                command.CommandType = CommandType.StoredProcedure;
                command.CommandText = "dbo.HotelSearchByRidOrName";

                command.Parameters.Add(new SqlParameter("@Text", text));

                using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
                {
                    while (reader.Read())
                    {
                        items.Add(new HotelDo()
                        {
                            Name = SqlExtension.ReaderToStringConverter(reader["Name"]),
                            Id = SqlExtension.ReaderToIntConverter(reader["Id"]),
                            Rid = SqlExtension.ReaderToStringConverter(reader["RIDHotel"]),
                            IdPms = SqlExtension.ReaderToNullableIntConverter(reader["IdPms"]),
                            LinkResaWeb = SqlExtension.ReaderToStringConverter(reader["LinkResaWeb"]),
                            LinkPms = SqlExtension.ReaderToStringConverter(reader["LinkPms"]),
                            IdBrand = SqlExtension.ReaderToNullableIntConverter(reader["IdBrand"]) ?? 0,
                            IsOnline = SqlExtension.ReaderToBoolConverter(reader["IsOnline"]) ?? false,
                            CodeCountry = SqlExtension.ReaderToStringConverter(reader["CodeCountry"])
                        });
                    }
                }
            }
            return items;
        }
        catch (Exception e)
        {
            var errorMessage = $"HotelRepository Find, text {text} ";
            _loggerService.Trace(LogSeverity.Error, errorMessage, e);

            throw new DalException() { Source = errorMessage, };
        }
        finally
        {
            _dbConnection.Close();
        }
    }

    public List<HotelDo> GetAll()
    {
        try
        {
            _dbConnection.Open();

            var items = new List<HotelDo>();
            using (var command = _dbConnection.CreateCommand())
            {
                command.CommandType = CommandType.StoredProcedure;
                command.CommandText = "dbo.HotelGetAll";

                using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
                {
                    while (reader.Read())
                    {
                        bool.TryParse(reader["IsOnline"].ToString(), out var isOnline);

                        items.Add(new HotelDo()
                        {
                            Id = SqlExtension.ReaderToIntConverter(reader["Id"]),
                            Rid = SqlExtension.ReaderToStringConverter(reader["RIDHotel"]),
                            Name = SqlExtension.ReaderToStringConverter(reader["Name"]),
                            CodeCountry = SqlExtension.ReaderToStringConverter(reader["CodeCountry"]),
                            LinkPms = SqlExtension.ReaderToStringConverter(reader["LinkPms"]),
                            IdPms = SqlExtension.ReaderToNullableIntConverter(reader["IdPms"]),
                            IdBrand = SqlExtension.ReaderToNullableIntConverter(reader["IdBrand"]) ?? 0,
                            LinkResaWeb = SqlExtension.ReaderToStringConverter(reader["LinkResaWeb"]),
                            IsOnline = isOnline
                        });
                    }
                }
            }
            return items;
        }
        catch (Exception e)
        {
            var errorMessage = $"HotelRepository GetAllHotels";
            _loggerService.Trace(LogSeverity.Error, errorMessage, e);

            throw new DalException() { Source = errorMessage, };
        }
        finally
        {
            _dbConnection.Close();
        }
    }
}

谢谢你的帮助

EN

回答 1

Stack Overflow用户

发布于 2020-04-29 04:55:28

因此,基于您已有的内容,我为您设置了一个测试框架以供您遵循。为了简洁,我删除了不太重要的组件。

在你加入之前,我只想说出我的两点看法,如果你不知道如何做这类事情,你似乎或多或少处于初级职位或缺乏使用C#的经验,而且你也发现自己在一个或多或少成熟的公司中,并不关心开发部门,因为一个未被覆盖的项目只是被扔向你的方式,说你没有太多的资源来改善代码库。

  1. 只测试那些有商业价值的东西(如果它能让你看起来更好),那么你能为这段逻辑定价吗?(在这个行业里,没有人关心测试的难易程度,获得你的经验,好的声誉,一旦你开始感到无聊,就不要害怕离开那里。--

Main

代码语言:javascript
复制
void Main()
{
    var idIndex = 0;
    var ids = new string[] { "1", "2" };

    var mockDataReader = new Mock<IDataReader>();
    mockDataReader.SetupSequence(x => x.Read()).Returns(true).Returns(true).Returns(false);
    mockDataReader.SetupGet(x => x["Id"]).Returns(() => ids[idIndex]).Callback(() => idIndex++);

    var mockParameters = new Mock<IDataParameterCollection>();

    var mockCommand = new Mock<IDbCommand>();
    mockCommand.SetupGet(x => x.Parameters).Returns(mockParameters.Object);
    mockCommand.Setup(x => x.ExecuteReader(CommandBehavior.CloseConnection)).Returns(mockDataReader.Object);

    var mockConnection = new Mock<IDbConnection>();
    mockConnection.Setup(x => x.CreateCommand()).Returns(mockCommand.Object);

    var repo = new HotelRepository(mockConnection.Object);

    var result = repo.Find("search");

    Assert.Equal("1", result[0].Id);
    Assert.Equal("2", result[1].Id);
}

存储库

代码语言:javascript
复制
public class HotelRepository
{
    private readonly IDbConnection _dbConnection;

    public HotelRepository(IDbConnection dbConnection)
    {
        _dbConnection = dbConnection;
    }

    public List<Pony> Find(string text)
    {
        _dbConnection.Open();

        var items = new List<Pony>();
        using (var command = _dbConnection.CreateCommand())
        {
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = "dbo.HotelSearchByRidOrName";

            command.Parameters.Add(new SqlParameter("@Text", text));

            using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                    items.Add(new Pony
                    {
                        Id = reader["Id"].ToString()
                    });
                }
            }
        }
        return items;
    }
}

只是一匹笨拙的小马

代码语言:javascript
复制
public class Pony {
    public string Id { get; set; }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61482513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档