【问题标题】:how to unit test following Method, returning value using "ref"如何对以下方法进行单元测试,使用“ref”返回值
【发布时间】:2010-01-19 18:11:58
【问题描述】:

我在业务层也有类似的方法。我是单元测试的新手,有时会感到困惑。对于一个想法,你能建议什么是测试这种方法的更好方法 行为?我正在使用 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() = 使用 DB 中存储过程的函数的名称

它会添加一条新记录“类别”并返回其自动生成的 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”检查返回的值
  • 您更喜欢测试什么而不是测试?如果能列出就太好了

【问题讨论】:

  • 你为什么首先使用 ref 参数?只需将其设为返回值即可。
  • 为什么 categoryId 可以为空?如果你将它转换为 int 并且它是 null 你会得到一个异常。
  • @jon Skeet:使用 ref 不确定如何从存储过程返回结果。 @magnus:根据您的建议修复

标签: c# unit-testing stored-procedures nunit ref


【解决方案1】:

根据适配器类型的特性,有几个选项。如果 AddDeveloperCategoryReturnID 是 virtualinterface 成员,您很可能使用 Test Double(手动或动态模拟)将其行为替换为一些特定于测试的行为。

如果是非虚拟方法,您有两种选择:

  • 重构方法以使其更具可测试性。
  • 编写一个涉及数据库往返的自动化测试。

涉及数据库的自动化测试比纯单元测试更难编写和维护几个数量级,因此我倾向于选择重构选项。

另一方面,如果您认为存储过程代表了应由自动化测试保护的有价值的代码资产,那么您别无选择,只能编写数据库测试。

【讨论】:

  • 它是一个虚拟方法,这是一个签名:public virtual object AddDeveloperCategoryReturnID(string NAME, ref global::System.Nullable CATEGORY_ID) {//设计师生成代码}
  • 你也许可以模拟它,但这取决于Adapter 是什么。它是公共可写财产还是公共虚拟财产。在第一种情况下,您可以将其替换为测试替身。在后一种情况下,您可以使用 Extract & Override 单元测试模式。
【解决方案2】:

我首先转换Adapter.AddNewBlogCategoryReturnID(categoryName, ref categoryID),这样它就不会通过引用返回变量,而是简单地返回值。

然后,我会将其提取到虚拟方法中。

为了测试AddNewCatRetID,我将扩展该类以创建可测试的版本,并重写该虚拟方法以返回存储在公共变量中的int?

这样,当您测试以查看在数据库中有 0 的情况下调用 AddNewCatRetID 时会发生什么时,您实际上不需要在数据库中放入 0 - 您只需将该参数设置为你的类的可测试版本,当你的测试调用AddNewCatRetID时,如果访问数据库,它只会返回你设置的值。如果您可以避免访问数据库,则可以保证您的测试更快,并且由于它是 MS 生成的适配器,因此实际上不需要对其进行测试 - 您只关心您的方法如何处理适配器返回的内容。

【讨论】:

  • 你将如何测试一个“ref”,如果它是唯一/最好的选择?
  • 如果ref 是唯一的选择,我会让虚拟方法也通过引用返回值。老实说,我对通过 ref 返回不是很熟悉,但如果我理解正确,您会将 ref 变量的值设置为您的公共字段的值。
  • 虚拟方法由设计者自动生成。我尝试过的一个选择是将这个自动生成的方法包装到我的自定义方法中,以获得所需的结果并正常返回它。但只是为了单元测试
猜你喜欢
  • 1970-01-01
  • 2014-05-10
  • 2016-10-18
  • 2011-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多