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

时间:2009-12-21 05:06:48

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

我是Mocking的新手,对单元测试有点熟悉,最后决定用一个严格的TDD方法开始一个新项目。但是我有一个服务类和方法,我需要回顾性地添加测试,因为它已经从原型中提升。

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

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(...)测试的所有排列,但是对于第一个测试,只需测试一个有效的websiteId和{{已传入1}},如果是,则返回有效的pageKey实例,并将单词测试断言为true。

Page是一个WCF服务客户端,之前它被包含在testServiceClient语句中,但是我已经将它移出了它,希望能够通过依赖注入来实现它,因为我觉得这将是测试所需的第一步,从我的理解,我需要给它一个假/嘲笑? wcf客户端而不是using()返回已知的内存数据集?希望我在那里走上正轨。

所以这是我单元测试的初始蓝图(我正在使用Moq框架,testServiceClient.GetPage()Setup()的新版本,如果您还没有使用Moq的最新版本):

Expect()

我不知道从哪里开始,或者我是否在正确的轨道上?我可以确认上面没有语法错误,我确实收到了一个例外:

/// <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(...)websiteId有效,但我不希望它使用真实pageKey 1}} WCF调用...希望我理解正确模拟的想法。当你在该服务上使用testServiceClient.GetPage()时,我是否通过Moq正确地告诉了它,实际上只返回一个新的页面实例?

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

1 个答案:

答案 0 :(得分:4)

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

但是,当您定义安装程序时,Moq必须能够识别您的方法,并且看起来好像您以某种方式指示了接口上不存在的方法。

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

如果你仔细看看Setup方法,你会发现它确实是一个通用方法,所以当你调用它时没有通用参数就会进行类型推断。

我的猜测是websiteId的声明在某种程度上与GetPage的声明冲突。例如,如果websiteId被声明为object,则Moq将使用此签名来管理方法:

Page GetPage(object x, string y);

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

无论如何,一旦你设法让安装程序工作,你对单元测试的基本想法似乎很好。您可以做的不仅仅是声明实例不为null,因为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);
}

注意更有价值的断言。