如何对 WCF 服务进行单元测试?

Posted

技术标签:

【中文标题】如何对 WCF 服务进行单元测试?【英文标题】:How do I unit test a WCF service? 【发布时间】:2010-09-07 10:23:40 【问题描述】:

我们有一大堆 DLL,可以让我们访问我们的数据库以及其他应用程序和服务。

我们使用瘦 WCF 服务层包装了这些 DLL,然后我们的客户会使用该服务层。

我有点不确定如何编写只测试 WCF 服务层的单元测试。我应该只为 DLL 编写单元测试,并为 WCF 服务编写集成测试吗?我会很感激任何智慧......我知道如果我的单元测试实际上进入数据库,它们实际上不会是真正的单元测试。我也明白我真的不需要在单元测试中测试 WCF 服务主机。

所以,我对究竟要测试什么以及如何测试感到困惑。

【问题讨论】:

无需对 WCF 服务进行 UNIT 测试,编写 INTEGRATION 测试完全没问题。 避免使用模拟,一个单元不是一个没有任何外部依赖的类。一个单元是业务逻辑的端到端切片,即使它涉及数据库。您始终可以使用内存,甚至更好地使用 BerkeleyDB 等嵌入式数据库进行测试。您不需要驻留在其他机器上的实际数据库。这样您就可以有效地测试您的单元,而无需大量模拟。 【参考方案1】:

如果您想对 WCF 服务类进行单元测试,请确保在设计它们时考虑到松散耦合,这样您就可以模拟每个依赖项,因为您只想测试服务类本身内部的逻辑。

例如,在下面的服务中,我使用“Poor Man's Dependency Injection”打破了我的数据访问存储库。

Public Class ProductService
    Implements IProductService

    Private mRepository As IProductRepository

    Public Sub New()
        mRepository = New ProductRepository()
    End Sub

    Public Sub New(ByVal repository As IProductRepository)
        mRepository = repository
    End Sub

    Public Function GetProducts() As System.Collections.Generic.List(Of Product) Implements IProductService.GetProducts
        Return mRepository.GetProducts()
    End Function
End Class

在客户端,您可以使用服务契约的接口模拟 WCF 服务本身。

<TestMethod()> _
Public Sub ShouldPopulateProductsListOnViewLoadWhenPostBackIsFalse()
    mMockery = New MockRepository()
    mView = DirectCast(mMockery.Stub(Of IProductView)(), IProductView)
    mProductService = DirectCast(mMockery.DynamicMock(Of IProductService)(), IProductService)
    mPresenter = New ProductPresenter(mView, mProductService)
    Dim ProductList As New List(Of Product)()
    ProductList.Add(New Product)
    Using mMockery.Record()
        SetupResult.For(mView.PageIsPostBack).Return(False).Repeat.Once()
        Expect.Call(mProductService.GetProducts()).Return(ProductList).Repeat.Once()
    End Using
    Using mMockery.Playback()
        mPresenter.OnViewLoad()
    End Using
    'Verify that we hit the service dependency during the method when postback is false
    Assert.AreEqual(1, mView.Products.Count)
    mMockery.VerifyAll()
End Sub

【讨论】:

来自martinfowler.com/bliki/InterfaceImplementationPair.html 当你不打算有多个实现时使用接口是保持一切同步的额外努力。此外,它隐藏了你实际提供多个实现的情况。在***.com/questions/90851/…中查看更多示例【参考方案2】:

这取决于瘦 WCF 服务的作用。如果它真的很薄并且那里没有有趣的代码,请不要费心对其进行单元测试。如果那里没有真正的代码,不要害怕不进行单元测试。如果测试不能比被测代码至少简单一级,请不要打扰。如果代码是愚蠢的,那么测试也会是愚蠢的。您不想维护更多愚蠢的代码。

如果您可以进行一直到数据库的测试,那就太好了!它甚至更好。这不是“真正的单元测试”吗?根本不是问题。

【讨论】:

【参考方案3】:

您的服务的消费者并不关心您的服务下的内容。 要真正测试您的服务层,我认为您的层需要深入到 DLL 和数据库并至少编写 CRUD 测试。

【讨论】:

以上是关于如何对 WCF 服务进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

如何对我的 WCF 客户端类进行单元测试?

WCF 单元测试

串行执行单元测试(而不是并行)

单元测试 WCF 服务时,AddressAccessDeniedException“您的进程没有访问此命名空间的权限”

在 Grails 中对服务进行单元测试时如何模拟请求

将数据注入 WCF 服务