.net 具有WCF调用的单元测试服务(MSUnit&x2B;Moq)

.net 具有WCF调用的单元测试服务(MSUnit&x2B;Moq),.net,unit-testing,dependency-injection,mocking,moq,.net,Unit Testing,Dependency Injection,Mocking,Moq,我不熟悉Mocking,对单元测试有点熟悉,最后我决定用严格的TDD方法开始一个新项目。但是,我有一个服务类和方法需要回顾性地添加测试,因为它是从原型升级而来的 我不知道从哪里开始,但在这个特定的测试中,涉及的类和方法如下: public class PageService : IPageService { private readonly ITestService testServiceClient; public PageService(ITestService testS

我不熟悉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
pageKey
,如果是,则接收一个有效的
Page
实例,并断言单元测试为true

testServiceClient
是一个WCF服务客户机,以前它被包装在
using()
语句中,但我已经将它移出了该语句,希望通过依赖项注入来实现它,因为我觉得这将是测试所需的第一步,据我所知,我需要给它一个假的/模拟的?wcf客户端,其中
testServiceClient.GetPage()
返回内存中已知的数据集?希望我在那里走的是正确的道路

下面是我的单元测试的初始蓝图(我正在使用Moq框架,
Setup()
Expect()
的新版本,如果您没有使用最新版本的Moq):

我只知道我希望我的
服务.GetPage(…)
返回一个新实例,因为
websiteId
pageKey
是有效的,但是我不希望它使用真正的
testServiceClient.GetPage()
WCF调用。。。希望我能正确理解嘲弄的意思。当您在该服务上使用
testServiceClient.GetPage
时,我是否通过Moq正确地告诉了您,实际上只是返回了一个新的page实例


任何澄清都将不胜感激!谢谢大家

我想说,你走在正确的轨道上。如果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);
}
[TestMethod]
public void Test_Valid_Website_和_Valid_PageKey_返回_Page()的_Valid_实例_
{
//安排
Page=null;
//表演
var newPage=newPage(){Title=“模拟版本!?”};
testServiceClient=new Mock();
testServiceClient.Setup(x=>x.GetPage(websiteId,“关于我们”)).Returns(newPage);
服务=新的页面服务(testServiceClient.Object);
page=service.GetPage(websiteId,“关于我们”);
//断言
Assert.AreEqual(新建页,第页);
}

请注意更有价值的断言。

+1回答很好-@GONeale,为了证实Mark所说的,我使用MOQ和一个返回页面的界面运行了一个快速测试-它工作正常。看起来你是在模拟一个具体的实例,其中GetPage并没有声明为虚拟的。ITestService是一个WCF生成的服务客户机,(右键单击项目->添加服务引用)类型。鉴于此,我认为我不能将其声明为
virtual
,因为它是一个自动生成的类。但是,我可以创建一个简单的WCF调用方类,并将其虚拟化,这会有帮助吗?感谢Assert提示。声明
testServiceClient.Setup(x=>x.GetPage(..)。Returns(newPage)
告诉任何对该方法名称的调用(嵌套,即使对象的方法作为参数传入,例如
新页面服务(testServiceClient.object)
)要实际不运行实际(wcf)方法,而只返回一个
newPage
实例?这就是为什么需要
virtual
,它会用全新的方法内容覆盖它的原因吗?请原谅我对嘲弄的无知,我正在努力追赶,但是在我的工作场所,这是一个微妙的平衡,在让这个项目出门与允许研究的时间之间。典型的故事。w00t!!!我创建了一个
WcfPageService
并声明了一个执行WCF往返的
GetPage()
virtual方法,然后将其用作我的可模拟对象!工作得很有魅力!!谢谢各位,你们可以在这里查看适用的代码
Page GetPage(Guid x, string y);
[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);
}