除了集成测试之外,单元测试是否会为这个 DAL 提供程序示例添加任何价值?
public List<int> GetPortfolioList()
{
using (var connection = new SqlConnection("<connectionString>"))
using (var command = new SqlCommand("SELECT * FROM Portfolio", connection))
{
connection.Open();
var portfolioTable = SqlHelper.GetDataTable(command);
var portfolios = from DataRow row
in portfolioTable.Rows
select int.Parse(row["Portfolio"].ToString());
return portfolios.ToList();
}
}
正如名称(和代码)所示,在 SQL DAL 提供程序中采用此方法来检索投资组合列表。由于用于集成测试的数据库表包含一组相当静态的数据,因此我们可以针对多种期望进行断言。例如,投资组合列表将: - 不能为空 - 包含某些已知值 - 不包含重复项
经过同行评审后,有人坚持认为该代码没有经过适当的测试(单独),因为它依赖于数据库访问。在大多数价值是在确保此方法从状态得到保证的数据库返回数据中找到的情况下,我无法看到模拟数据库调用以便为此方法编写单元测试的价值。我错过了什么吗?
public List<int> GetPortfolioList()
{
using (var connection = new SqlConnection("<connectionString>"))
using (var command = new SqlCommand("SELECT * FROM Portfolio", connection))
{
connection.Open();
var portfolioTable = SqlHelper.GetDataTable(command);
var portfolios = from DataRow row
in portfolioTable.Rows
select int.Parse(row["Portfolio"].ToString());
return portfolios.ToList();
}
}
Take this method in a SQL DAL provider to retrieve a list of portfolios, as the name (and code) suggests. Because the database table for integration testing contains a fairly static set of data we can Assert against several expectations. e.g. The list of portfolios will:
- not be empty
- contain certain known values
- contain no duplicates
Following a peer review, someone insisted that this code isn't being properly tested (in isolation) because it relies on database access. In the case that most of the value is found in ensuring that this method returns data from a database whose state is guaranteed, I've been unable to see the value in mocking away the database call in order to write a unit test for this method. Am I missing something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我会采取相反的观点,因为我刚刚写完一个假数据库(在内存列表中使用)以使 linq to sql (或 linq to everything)单元可测试。
这是我用来选择一种合适的方法来伪造/模拟数据库的一个问题。 (不过,从阅读你的代码来看,嵌入的“SELECT * FROM”意味着你更依赖于 SQL 而不是 linq,这将使你更难将你的代码分解为由 SQL Server 执行的内容以及 linq 能够处理的内容
人们如何使用 Linq to SQL 进行单元测试
我现在可以运行单元测试,这些测试会成功或失败,具体取决于我的 linq 查询的适用性即使数据库已从墙上拔下 例如,
如果 row["Portfolio"].ToString() 为 null,则代码如何反应,当不返回任何行或返回 2 时,代码如何反应
?测试,nunit 是一个不错的集成测试方式,只是要小心不要将它们称为单元测试,以免纯粹主义者对此感到不安。
I'll take the contrary view because I just finished writing a fake db (using in memory lists) to make linq to sql (or linq to anything) unit testable.
This is one question I used to pick a suitable way to fake/mock the database. (from reading your code though, the embedded "SELECT * FROM" means you are leaning on SQL more than linq, which will make it harder to factor your code into stuff that has to be executed by SQL Server and stuff that linq is capable of dealing with.
How are people unit testing code that uses Linq to SQL
I can now run unit tests that will succeed or fail depending on the suitability of my linq query even if the database is unplugged from the wall.
For example, how is your code to react if row["Portfolio"].ToString() is null, how does the code react when this doesn't return any rows, or returns 2?
And even if you are only doing integration tests, nunit is not a bad way to integration tests, just be careful not to call them unit tests, lest a purist get upset about it.
该方法使用 Linq 将数据库中的一些值投影到整数列表中 - 您可能想测试它是否正确执行此操作。
我会将代码分为两部分 - 数据检索和投影(Linq 查询) - 然后您可以使用模拟数据测试 linq 查询,而无需模拟数据库。
我还想说,单元测试数据访问代码没有什么价值。
The method uses Linq to project some values from the DB into a list of integers - you may want to test that it does that correctly.
I would split the code into two - the data retrieval and the projection (Linq query) - you could then test the linq query with mock data, without needing to mock the database.
I would also say there is little value in unit testing data access code.
作为一名测试纯粹主义者,我相信我无法对 DAL 进行“单元测试”,因为我无法孤立地进行测试。这意味着我的代码的一部分(与数据库交互的代码)没有进行单元测试。上面的代码看起来不错;只需确保它作为一个更大的合约的一部分存在,您可以在其他对象中进行测试。
不过,我确实通过构建数据库、为其播种并确保我的 DAL 正常工作来执行集成测试。
As a testing purist, I believe that I cannot "unit test" a DAL because I cannot do it in isolation. This means that a portion of my code, the one interacting with the database, goes without unit testing. The code above looks fine; just make sure that it exists as part of a larger contract that you can test in other objects.
I do perform integration testing, though, by building a database, seeding it, and ensuring that my DAL works.
我同意你的观点,这里唯一的价值是集成测试,如果不迂腐的话,真的没有什么可以进行单元测试的。
当然,此方法的任何调用者的单元测试代码都应该模拟此方法。
e:MathewMartin 上面提到的例外情况是我认为在这种情况下唯一值得进行单元测试的事情。
I would agree with you, the only value here will be integration testing, there's really nothing to unit test without being pedantic.
The unit test code for any callers of this method should mock this method away, of course.
e: The exception cases MathewMartin mentions above would be the only things I would consider worth unit testing in this scenario.