Unit testing 使用Moq模拟方法的问题

Unit testing 使用Moq模拟方法的问题,unit-testing,testing,moq,Unit Testing,Testing,Moq,我有下面的类,它有两个静态方法Retrieve和RetrieveWithQuery。 在这里列出的类下面,我包含了一个测试片段。 除最后一次断言外,所有测试均失败,并显示以下消息: 失败的TestMethod2 MoqTest Assert.AreEqual失败。预期:。实际值: 我知道问题可能是我在模拟中设置的查询 是与RetrieveWithQuery方法中使用的查询不同的实例。 这就是为什么is会返回null 在一个完美的世界里,我会简单地重新考虑服务类,不幸的是,我是 使用已投入生产的遗

我有下面的类,它有两个静态方法Retrieve和RetrieveWithQuery。 在这里列出的类下面,我包含了一个测试片段。 除最后一次断言外,所有测试均失败,并显示以下消息:

失败的TestMethod2 MoqTest Assert.AreEqual失败。预期:。实际值:

我知道问题可能是我在模拟中设置的查询 是与RetrieveWithQuery方法中使用的查询不同的实例。 这就是为什么is会返回null

在一个完美的世界里,我会简单地重新考虑服务类,不幸的是,我是 使用已投入生产的遗留代码。目标是首先完成 测试,然后重新生成代码,并在更新产品之前运行回归测试 环境

是否有解决方法或不同的方法来测试这一点

public class MyService  
{
    public virtual string RetrieveMethod(string account)
    {
        if (account == "The abc company")
        {
            return "Peter Smith";
        }

            return "John Doe";
    }

    public virtual string RetrieveMethod(MyQuery query)
    {
        return RetrieveMethod(query.QueryString);   
    }

    public static string Retrieve(MyService service, string value)
    {
        return service.RetrieveMethod(value);
    }

    public static string RetrieveWithQuery(MyService service, string value)
    {
        var query = new MyQuery
        {
            QueryString = value
        };

        return service.RetrieveMethod(query);
    }

}

public class MyQuery
{
    public string QueryString;
}



    [TestMethod]
    public void TestMethod2()
    {
        var mockService = new Mock<MyService>();

        const string company = "The abc company";
        const string expectedContact = "Peter Smith";

        var queryAccount = new MyQuery
                        {
                            QueryString = company
                        };

        // Setup base retrieve
        mockService.Setup(myServ => myServ.RetrieveMethod(company)).Returns(expectedContact);

        // Setup base retrieve with query
        mockService.Setup(myServ => myServ.RetrieveMethod(queryAccount)).Returns(expectedContact);

        // test base retrieve with query - PASS
        Assert.AreEqual(expectedContact, mockService.Object.RetrieveMethod(queryAccount));

        // test static method retrieve - PASS
        Assert.AreEqual(expectedContact, MyService.Retrieve(mockService.Object, company));

        // test static method retrieve with query - FAIL
        Assert.AreEqual(expectedContact, MyService.RetrieveWithQuery(mockService.Object, company));
    }
公共类MyService
{
公共虚拟字符串检索方法(字符串帐户)
{
如果(账户=“abc公司”)
{
返回“彼得·史密斯”;
}
返回“John Doe”;
}
公共虚拟字符串检索方法(MyQuery)
{
返回RetrieveMethod(query.QueryString);
}
公共静态字符串检索(MyService服务,字符串值)
{
return service.RetrieveMethod(值);
}
公共静态字符串检索WithQuery(MyService服务,字符串值)
{
var query=newmyquery
{
查询字符串=值
};
return service.RetrieveMethod(查询);
}
}
公共类MyQuery
{
公共字符串查询字符串;
}
[测试方法]
公共void TestMethod2()
{
var mockService=new Mock();
const string company=“abc公司”;
const string expectedContact=“Peter Smith”;
var queryAccount=new MyQuery
{
查询字符串=公司
};
//设置基检索
mockService.Setup(myServ=>myServ.RetrieveMethod(company)).Returns(expectedContact);
//设置基检索与查询
mockService.Setup(myServ=>myServ.RetrieveMethod(queryAccount)).Returns(expectedContact);
//使用查询进行测试库检索-通过
AreEqual(expectedContact、mockService.Object.RetrieveMethod(queryAccount));
//测试静态方法检索-通过
AreEqual(expectedContact,MyService.Retrieve(mockService.Object,company));
//使用查询检索测试静态方法-失败
AreEqual(expectedContact,MyService.RetrieveWithQuery(mockService.Object,company));
}

为您的设置尝试以下方法:

    // Setup base retrieve with query
    mockService.Setup(myServ => myServ.RetrieveMethod(It.Is<Query>(q=>q.QueryString == queryAccount.QueryString)).Returns(expectedContact);
//使用查询检索设置库
mockService.Setup(myServ=>myServ.RetrieveMethod(It.Is(q=>q.QueryString==queryAccount.QueryString)).Returns(expectedContact);
或者可以重载Equals for Query,以便创建的查询等于expectedQuery


该页面提供了这方面的好例子,还有更多的例子,这些例子应该会对您有很大帮助。

请尝试以下设置:

    // Setup base retrieve with query
    mockService.Setup(myServ => myServ.RetrieveMethod(It.Is<Query>(q=>q.QueryString == queryAccount.QueryString)).Returns(expectedContact);
//使用查询检索设置库
mockService.Setup(myServ=>myServ.RetrieveMethod(It.Is(q=>q.QueryString==queryAccount.QueryString)).Returns(expectedContact);
或者可以重载Equals for Query,以便创建的查询等于expectedQuery


该页面提供了这方面以及更多方面的好例子,应该会有很大帮助。

感谢您的回复,我对您提供的答案还有另一个问题。如果有其他对象级别需要模拟,我将如何进行模拟?我尝试了以下代码,但失败了。在这种情况下,需要模拟一个请求和查询:mockSservice.Setup(myServ=>myServ.RetrieveRequestMethod(It.Is(r=>r.Query==It.Is(q=>q.QueryString==company))).Returns(expectedContact);该特定行将成为
mockService.Setup(myServ=>myServ.RetrieveRequestMethod(It.Is(r=>r.Query.QueryString==company))。Returns(expectedContact);
。您应该将匹配约束的主体视为与您在手动模拟中编写的内容相同。此外,请查看quickstart页面和其他Moq文档,它们都非常好:。感谢您的回答,关于您提供的答案,我还有另一个问题。如果有其他对象,我将如何处理el to mock?我尝试了以下代码,但失败了。在这种情况下,需要模拟一个请求和查询:mockService.Setup(myServ=>myServ.RetrieveRequestMethod(it.is(r=>r.query==it.is(q=>q.QueryString==company))。返回(expectedContact);该特定行将成为
mockService.Setup(myServ=>myServ.RetrieveRequestMethod(It.Is(r=>r.Query.QueryString==company)))。返回(expectedContact)。您应该将匹配约束的主体视为与您在手动翻滚模拟中编写的内容相同。另外,请查看快速启动页面和其他Moq文档,它们非常好:。