c# - .NET 中的单元测试服务层

标签 c# unit-testing design-patterns moq

我正在开发一个新的 MVC 5 应用程序。我的项目中有一个集成层,其中有对外部 Web 服务的服务引用。

然后我创建了一个具有一些方法的接口(interface) - 然后我有一个服务类,如下所示:

public class MyService : IMyService
{
    private readonly ExternalServiceClient _serviceClient;

    public MyService()
    {
        _serviceClient = new ExternalServiceClient ("WSHttpBinding_IMyService");
    }

    public string GetName(Coordinate[] coordinates)
    {
        string name = string.Empty;

        name = _serviceClient.GetInformationsForCoordinates(coordinates);

        return name;
    }

请注意,这是精简的,实际上会添加带有异常处理等的 try catch block

我有一个用于集成层单元测试的 Integration.Tests 项目。测试 GetName 方法的最佳实践方法是什么。我是否应该向测试项目中的服务端点添加另一个服务引用,或者如果我们正在使用 Moq,我是否可以创建 Web 层将调用的实际服务的实例 - 以及如何完成?

最佳答案

适合您情况的最佳实践在于您的架构设计。

您的服务显然依赖于 ExternalServiceClient,并且您在 MyService 类中实例化它,这不允许您轻松切换依赖性,导致您需要测试时很头疼。

真正的问题应该是:

How may I design my service in order to make it easily testable?

答案是Dependency Injection .

因为您将能够模拟 MyService 依赖项,您将能够彻底测试它并能够通过红绿重构证明您的服务完美运行。

依我拙见,你的类(class)应该是这样的:

public class MyService : IMyService {
    public MyService(ExternalServiceClient serviceClient) {
        externalServiceClient = serviceclient;
    }

    public string GetName(Coordinate[] coordinates) {
        string name = string.Empty;
        name = externalServiceClient.GetInformationForCoordinates(coordinates);
        return name;
    }

    private readonly ExternalServiceClient externalServiceclient;
}

这样,您就可以随意替换依赖项,因此可以使用 mock。

使用 NUnitMoq,您可以按如下方式测试您的服务:

[TestFixture]
public class MyServiceTests {
    [TestFixture]
    public class GetCoordinates : MyServiceTests {
        // Given
        string expected = "Name";
        Coordinate[] coordinates = new Coordinate[] { ... }
        externalServiceClientMock.Setup(esc => esc.GetInformationForCoordinates(coordinates)).Returns(expected);

        // When
        string actual = myService.GetName(coordinates);

        // Then
        externalServiceClientMock.Verify(esc => esc.GetInformationCoordinates(coordinates));
        Assert.AreEqual(expected, actual);
    }

    [SetUp]
    public void MyServiceSetup() {
        externalServiceClientMock = new Mock<ExternalServiceClient>("WSHttpBinding_IMyService");
        myService = new MyService(externalServiceClientMock.Object);
    }
    
    private Mock<ExternalServiceClient> externalServiceClientMock;
    private MyService myService;
}

关于c# - .NET 中的单元测试服务层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23409275/

相关文章:

c++ - 是否可以将非枚举值作为枚举函数参数传递?

unit-testing - PHPUnit - Setter 不修改我的模拟

cocoa - 委托(delegate)和通知之间的显着差异

c++ - 这种设计是标准设计模式之一吗?

c# - 最新 DotNet 技术的最佳在线视频培训网站

c# - 使用可能有或没有尾随/的 Uri 字符串

c# - 正则表达式 - C# 的行为不同于 Perl/Python

c# - 基于 WPF 中的 TextBox Focus 更改图像颜色?

unit-testing - 如何在 Clojure 中测试高阶函数?

java - Java 动态代理与常规代理的有用性