.net - 具有 WCF 调用的单元测试服务 (MSUnit + Moq)

标签 .net unit-testing dependency-injection mocking moq

我是 Mocking 的新手,对单元测试有点熟悉,最后决定硬着头皮开始一个新项目,从严格的 TDD 方法开始。但是,我有一个服务类和方法,我需要追溯添加测试,因为它是从原型(prototype)提升的。

我不知道在这个特定的测试中从哪里开始,这是所涉及的类和方法:

public class PageService : IPageService
{
    private readonly ITestService testServiceClient;

    public PageService(ITestService testServiceClient)
    {
        this.testServiceClient = testServiceClient;
    }

    public Page GetPage(Guid websiteId, string pageKey)
    {
        Page builtPage = null;

        // WCF SERVICE CALL I DO NOT WANT EXECUTING WHEN RUNNING UNIT TEST
        // BUT RATHER WANT A BLANK NEW INSTANCE OF "PAGE" CREATED USING MOQ??
        var page = testServiceClient.GetPage(websiteId, pageKey);

        if (page == null)
            return null;

        builtPage = new Page();

        [code here to build builtPage if input params ok] ...

        return builtPage;
    }
}

我正在努力做的是写一个测试,希望我可以从这个测试中扩展 GetPage(...) 的所有排列测试,但对于第一个,只需测试有效的 websiteIdpageKey已传入,如果是,则接收有效的 Page实例返回并对单元测试断言 true。
testServiceClient是一个 WCF 服务客户端,它被包装在 using() 中之前的声明,但我已经将其移出,希望通过依赖注入(inject)来实现它,因为我觉得这将是测试所需的第一步,据我了解,我需要给它一个假的/模拟的? wcf 客户端,而不是 testServiceClient.GetPage()返回一个已知的内存数据集?希望我在那里走在正确的轨道上。

所以这是我的单元测试的初始蓝图(我使用的是 Moq 框架,Setup()Expect() 的新版本,如果你没有使用最新版本的 Moq):
/// <summary>
/// Tests service returns a valid instance of type `Page` when a valid website and valid page key is tested.
/// </summary>
[TestMethod]
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page()
{
    // Arrange
    Page page = null;

    // Act
    var newPage = new Page() { Title = "Mocked Version!?"};

    testServiceClient = new Mock<ITestService>();
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage);

    service = new PageService(testServiceClient.Object);
    page = service.GetPage(websiteId, "about-us");

    // Assert
    Assert.IsInstanceOfType(page, typeof(Page), "Object was not of expected instance type.");
}

我不知道从这里去哪里,或者我是否走在正确的轨道上?我可以确认上面没有语法错误,并且确实收到了异常:
System.ArgumentException: Invalid setup on a non-overridable member:
x => x.GetPage(websiteId, "about-us").

我只知道我想要我的service.GetPage(...)返回一个新实例,如 websiteIdpageKey是有效的,但我不希望它使用真正的 testServiceClient.GetPage() WCF 调用...希望我能正确理解模拟的想法。当您使用 testServiceClient.GetPage 时,我是否通过最小起订量正确告知了它?在该服务上,实际上只是返回一个新的页面实例?

非常感谢任何澄清!多谢你们!

最佳答案

我会说你走在正确的轨道上。如果 ITestService 确实是一个接口(interface)(如其名称所示),您将能够模拟它。

但是,当您定义设置时,Moq 必须能够识别您所指的方法,并且您似乎以某种方式指出了界面上不存在的方法。

您没有向我们展示 ITestService 接口(interface),我们也不知道 websiteId 的类型多变的。

如果您仔细查看 Setup 方法,您会发现它实际上是一个泛型方法,因此当您在没有泛型参数的情况下调用它时会进行类型推断。

我的猜测是 websiteId 的声明以某种方式与 GetPage 的声明发生冲突。例如,如果 websiteId被声明为 object , Moq 会处理一个带有这个签名的方法:

Page GetPage(object x, string y);

这不一样
Page GetPage(Guid x, string y);

无论如何,一旦你设法让安装程序工作,你对单元测试的基本想法似乎很好。您可以做的不仅仅是断言实例不为空,因为 Mock 将确保返回的实例与您最初设置的实例相同:
[TestMethod]
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page()
{
    // Arrange
    Page page = null;

    // Act
    var newPage = new Page() { Title = "Mocked Version!?"};

    testServiceClient = new Mock<ITestService>();
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage);

    service = new PageService(testServiceClient.Object);
    page = service.GetPage(websiteId, "about-us");

    // Assert
    Assert.AreEqual(newPage, page);
}

注意更有值(value)的断言。

关于.net - 具有 WCF 调用的单元测试服务 (MSUnit + Moq),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1938311/

相关文章:

c# - 检查数组是否包含相同的元素(顺序并不重要)c#

java - 测试 Ajax - 在 Apache Wicket 中提交表单

javascript - 为什么 Ruby irb 迭代这么慢?

c# - Composite 的简单注入(inject)器注册,结合了开放和封闭的通用实现

java - Autowired 为空且不适用于 Jersey + Spring

dependency-injection - 重用 CaSTLe Windsor 安装程序的注册?

c# - 带有AllowsTransparency = true的ResizeMode.CanResize不起作用

c# - 修改 XML 模式时如何管理 ItemChoiceType 枚举的更改?

c# - 在 C#/WPF 中发生特定事件时强制窗口闪烁

c# - 使用 AutoMapper 时如何跳过自定义验证属性?