加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

vb.net – 单元测试具体类

发布时间:2020-12-17 07:25:29 所属栏目:百科 来源:网络整理
导读:我继承了一个没有接口或抽象类的项目,即只有具体的类,我想引入单元测试.这些类包含许多函数,包含业务逻辑和数据逻辑;打破SOLID的所有规则( http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29). 我有一个想法.我正在考虑为每个设计不良的类创
我继承了一个没有接口或抽象类的项目,即只有具体的类,我想引入单元测试.这些类包含许多函数,包含业务逻辑和数据逻辑;打破SOLID的所有规则( http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29).

我有一个想法.我正在考虑为每个设计不良的类创建接口,公开所有功能.那么至少我可以模拟课程.

我对单元测试比较陌生(我有一个项目经验,在正确的地方使用接口非常发达).这样做是一个好主意,即为所有具体类创建接口(公开所有函数和子例程),仅用于单元测试?

我花了一些时间研究这个,但我没有找到答案.

解决方法

是的,这是一个良好的开端,但是,接口不是注入依赖项的优先级.如果所有遗留类都获得了接口,但内部隐藏它们仍然是相互依赖的,那么这些类仍然不容易测试.例如,假设你有两个看起来像这样的类:

Public Class LegacyDataAccess
    Public Function GetAllSales() As List(Of SaleDto)
        ' Do work with takes a long time to run against real DB
    End Function
End Class

Public Class LegacyBusiness
    Public Function GetTotalSales() As Integer
        Dim dataAccess As New LegacyDataAccess()
        Dim sales As List(Of SaleDto) = dataAccess.GetAllSales()
        ' Calculate total sales
    End Function
End Class

我知道你已经在说什么……“我希望遗留代码至少能够很好地分层”,但是让我们将其作为一些难以测试的遗留代码的例子.难以测试的原因是代码到达数据库并对数据库执行耗时的查询,然后从中计算结果.因此,为了在当前状态下测试它,您需要首先将一堆测试数据写入数据库,然后运行代码以查看它是否根据插入的数据返回正确的结果.必须编写类似的测试是有问题的,因为:

>编写代码来设置测试是一件痛苦的事
>测试将是脆弱的,因为它依赖于外部数据库正常工作,并且包含所有正确的支持数据
>测试运行时间太长

正如您所正确观察的那样,接口对于单元测试非常重要.因此,正如您所建议的那样,让我们??添加接口以查看它是否更容易测试:

Public Interface ILegacyDataAccess
    Function GetAllSales() As List(Of SaleDto)
End Interface

Public Interface ILegacyBusiness
    Function GetTotalSales() As Integer
End Interface

Public Class LegacyDataAccess
    Implements ILegacyDataAccess

    Public Function GetAllSales() As List(Of SaleDto) _
            Implements ILegacyDataAccess.GetAllSales
        ' Do work with takes a long time to run against real DB
    End Function
End Class

Public Class LegacyBusiness
    Implements ILegacyBusiness

    Public Function GetTotalSales() As Integer _
            Implements ILegacyBusiness.GetTotalSales
        Dim dataAccess As New LegacyDataAccess()
        Dim sales As List(Of SaleDto) = dataAccess.GetAllSales()
        ' Calculate total sales
    End Function
End Class

所以现在我们有接口,但实际上,它如何使它更容易测试?现在我们可以轻松地创建一个模拟数据访问对象,它实现了相同的接口,但这并不是核心问题.问题是,我们如何让业务对象使用该模拟数据访问对象而不是真实的?要做到这一点,您需要通过引入依赖注入将重构提升到一个新的水平.真正的罪魁祸首是业务类的以下行中的New关键字:

Dim dataAccess As New LegacyDataAccess()

业务类明显依赖于数据访问类,但目前它隐藏了这一事实.这是关于它的依赖性.它说,来吧,这很容易,只需调用此方法,我将返回结果 – 这就是所需要的.真的,它需要更多.现在,让我们说,我们阻止它说谎它的依赖关系,并使它如此毫不掩饰地声明它们,如下所示:

Public Class LegacyBusiness
    Implements ILegacyBusiness

    Public Sub New(dataAccess As ILegacyDataAccess)
        _dataAccess = dataAccess
    End Sub

    Private _dataAccess As ILegacyDataAccess

    Public Function GetTotalSales() As Integer _
            Implements ILegacyBusiness.GetTotalSales
        Dim sales As List(Of SaleDto) = _dataAccess.GetAllSales()
        ' Calculate total sales
    End Function
End Class

现在,正如您所看到的,这个类更容易测试.我们不仅可以轻松创建模拟数据访问对象,而且现在我们可以轻松地将模拟数据访问对象注入到业务对象中.现在我们可以创建一个模拟器,它可以快速轻松地返回我们想要返回的数据,然后查看业务类是否返回正确的计算 – 不涉及数据库.

不幸的是,虽然向现有类添加接口是轻而易举的,但重构它们以使用依赖注入通常需要更多的工作.您可能需要计划哪些类最有意义才能首先解决.您可能需要创建一些中间旧学校包装器,它们按照代码的方式工作,因此您在重构代码的过程中不会破坏现有代码.这不是一件快速而简单的事情,但是如果你有耐心并长期坚持下去,就有可能做到这一点,你会很高兴你做到了.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读