我在业务层也有类似的方法。我是单元测试的新手,有时会感到困惑。对于一个想法,你能建议一下,测试这种方法的更好方法是什么
行为?我正在使用 C# NUnit 和 Moq,
public int? AddNewCatRetID(string categoryName)
{
int? categoryID = 0;
Adapter.AddNewBlogCategoryReturnID(categoryName, ref categoryID);
if (categoryID.HasValue)
return categoryID;
return 0;
}
其中
Adapter
= Visual Studio 2008,数据集设计器生成的 TableAdater
AddDeveloperCategoryReturnID()
= 使用数据库中存储过程的函数名称
它添加新记录“类别”并返回其自动生成的 ID。如果它不为零,我们就将该结果进行进一步处理。
我知道不应该对与数据库交谈感兴趣,下面是过程,只是为了了解数据库中发生的情况,
PROCEDURE [dbo].[AddDeveloperCategoryReturnID]
@NAME NVARCHAR(MAX),
@CATEGORY_ID INT OUTPUT
AS
BEGIN
INSERT INTO [AllTimeGreatProgrammersDateBase].dbo.CATEGORIES(NAME )
VALUES (@NAME );
SET @CATEGORY_ID = SCOPE_IDENTITY();
SELECT @CATEGORY_ID;
END
一些问题
- 如何检查使用方法中的“ref”返回的值,
- 您希望测试什么以及不测试?如果能列出就太好了
I have similar methods in the business layer. I am new to unit testing and sometimes get confused. For an idea, can you suggest, what will be a better approach to test this method
behaviour? I am using C# NUnit and Moq
public int? AddNewCatRetID(string categoryName)
{
int? categoryID = 0;
Adapter.AddNewBlogCategoryReturnID(categoryName, ref categoryID);
if (categoryID.HasValue)
return categoryID;
return 0;
}
where
Adapter
= Visual Studio 2008, Data Set Designer generated TableAdater
AddDeveloperCategoryReturnID()
= Name of a function which utilises a Stored procedure in DB
It adds a new record, "Category" and returns its auto generated ID. If it is non zero, we take that result for further processing.
I know should not be interested in talking to Database, below is the procedure, just to give an idea about what is going on in DB
PROCEDURE [dbo].[AddDeveloperCategoryReturnID]
@NAME NVARCHAR(MAX),
@CATEGORY_ID INT OUTPUT
AS
BEGIN
INSERT INTO [AllTimeGreatProgrammersDateBase].dbo.CATEGORIES(NAME )
VALUES (@NAME );
SET @CATEGORY_ID = SCOPE_IDENTITY();
SELECT @CATEGORY_ID;
END
some issues
- how to check the values returned using "ref" from the method
- what will you prefer to test and not to test? will be great if can list
发布评论
评论(2)
根据适配器类型的特性,有多种选项。如果 AddDeveloperCategoryReturnID 是虚拟或接口成员,您很可能可以使用 测试替身(无论是手动的还是动态模拟)用一些特定于测试的行为替换其行为。
如果 是非虚拟方法,您有两个选择:
涉及数据库的自动化测试比纯单元测试更难编写和维护几个数量级,因此我倾向于选择重构选项。
另一方面,如果您认为存储过程代表了一种有价值的代码资产,应该通过自动化测试来保护,那么您别无选择,只能编写数据库测试。
There are several options depending on the characteristics of the Adapter type. If AddDeveloperCategoryReturnID is virtual or an interface member, you can most likely use a Test Double (either a hand-rolled one or a dynamic mock) to replace its behavior with some test-specific behavior.
If is a non-virtual method, you have two options:
Automated tests that involve the database are orders of magnitudes more difficult to write and maintain than pure unit tests, so I would tend to shoot for the refactoring option.
On the other hand, if you think that the stored procedure represents a valuable code asset that should be protected by an automated test, you have no recourse but to write the database test.
我首先会转换 Adapter.AddNewBlogCategoryReturnID(categoryName, refcategoryID),这样它就不会通过引用返回变量,而只是返回值。
然后,我将其提取到虚拟方法中。
为了测试
AddNewCatRetID
,我将扩展该类以创建可测试版本,并重写该虚拟方法以返回存储在公共变量中的int?
。这样,当您测试在数据库中有 0 的情况下调用
AddNewCatRetID
时会发生什么时,您不需要实际在数据库中放入 0 - 您只需设置它类的可测试版本上的参数,当您的测试调用 AddNewCatRetID 时,如果访问数据库,它只会返回您设置的值。如果您可以避免访问数据库,那么您的测试一定会更快,并且由于它是 MS 生成的适配器,因此实际上不需要测试它 - 您只关心您的方法对适配器返回的内容执行的操作。I'd first convert
Adapter.AddNewBlogCategoryReturnID(categoryName, ref categoryID)
so that instead of returning a variable by reference, it simply returned the value.Then, I would extract that into a virtual method.
To test
AddNewCatRetID
, I would extend the class to make a testable version, and override that virtual method to return anint?
stored in a public variable.That way, when you test to see what happens when you call
AddNewCatRetID
in a situation where there's a 0 in the database, you don't need to actually put a 0 in the database - you just set that parameter on the testable version of your class, and when your test callsAddNewCatRetID
, instead if hitting the database, it just returns the value you set. Your test is guaranteed to be faster if you can avoid hitting the database, and since it's MS's generated adapter, there's not really a need to test it - you only care about what your method does with what the adapter returns.