MOQ返回动态类型作为对象的问题

4

很抱歉如果这个问题已经被问过了,但我无处找到答案。

我的问题是在使用MOQ模拟返回一个动态类型的方法时。我正在使用一个使用动态类型的第三方库。MOQ似乎将动态类型强制转换为对象。

Mock<IFacebookHelper> mockFbHelp = new Mock<IFacebookHelper>();
mockFbHelp.Setup(x => x.Get("me")).Returns(new { email = "test@test.com", id="9999" });

在模拟的辅助器中的方法。
public dynamic Get(string p)
{
    var client = new FacebookClient(AccessToken);
    return client.Get("me");
}

使用模拟结果从控制器中获取代码。

_facebookHelper.AccessToken = accessToken;
dynamic result = _facebookHelper.Get("me");
int facebookId = int.Parse(result.id);  //This errors as id doesn't exist.

基本上,MOQ返回了一种动态类型的对象,需要将其强制转换为某些类型。有人知道如何解决这个问题吗?我认为这可能是因为MOQ不是使用.NET 4编写的,因此不支持动态类型?
编辑:实际上,我认为这不是一个MOQ问题,因为我创建了自己的模拟类,但仍然遇到了同样的问题。虽然我对动态类型还不太熟悉,所以不确定发生了什么。
编辑2-部分解答..问题与MOQ无关
实际上,问题似乎是由于在不同的程序集中创建了动态类型。虽然我使用了JObject类型解决了我的初始问题,但我仍然想解决这个问题。
namespace MyLib.Tools
{
    public interface IDynTest
    {
        dynamic GetData();
    }
}

namespace MyLib.Tools
{
    public class DynTest : Effect.Tools.IDynTest
    {
        public dynamic GetData() {
            return new { DynamicProperty = "hello" };
        }
    }
}

namespace Warrior.WebUI.Infrastructure
{
    public class UseDynTest
    {
        private readonly IDynTest dynTest;

        public UseDynTest(IDynTest dynTest)
        {
            this.dynTest = dynTest;
        }

        public string RetTest()
        {
            return dynTest.GetData().DynamicProperty;
        }
    }
}

namespace Warrior.Tests
{
    [TestClass]
    public class TestDynTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            //Mock<IDynTest> mockDynTest = new Mock<IDynTest>();
            //mockDynTest.Setup(x => x.GetData()).Returns(new { DynamicProperty = "From Unit Test" });

            DynTestProxy dynTestProxy = new DynTestProxy();

            UseDynTest useTest = new UseDynTest(dynTestProxy);

            string results = useTest.RetTest();

            Assert.AreEqual("From Unit Test", results);
        }
    }
}

namespace Warrior.Tests
{
    public class DynTestProxy:IDynTest
    {
        public dynamic GetData()
        {
            return (dynamic) new { DynamicProperty = "From Unit Test" };
        }
    }
}

有3个项目被命名空间MyLib, Warrior.WebUI和Warrior.Tests所表示。
由于测试失败并出现错误,'object' does not contain a definition for 'DynamicProperty',这是在RetTest()函数中发生的。

然而,如果我将DynTestProxy类简单地移动到Warrior.WebUI项目中,一切都正常工作。 我猜想,在不同程序集之间发送动态类型时会出现问题。


dynamic只是C#的一个关键字,没有类型“dynamic”。如果您通过动态本地使用任何具有名为“id”的属性/字段的对象,则应该可以工作。 - Ventsyslav Raikov
1个回答

8

我进行了一项简单的测试:

namespace ConsoleApplication5
{
    public interface IFacebookHelper { dynamic Get(string p); }

    class Program
    {
        static void Main(string[] args)
        {
            Mock<IFacebookHelper> mockFbHelp = new Mock<IFacebookHelper>();
            mockFbHelp.Setup(x => x.Get("me")).Returns(new { email = "test@test.com", id = "9999" });

            dynamic result = mockFbHelp.Object.Get("me");
            int facebookId = int.Parse(result.id);
            string email = result.email;
        }
    }
}

一切运作正常,我这里没有看到任何问题。

你确定你没有搞混一些东西吗?

看看你发布的方法:

public dynamic Get(string p)
{
    var client = new FacebookClient(AccessToken);
    return client.Get("me");
}

也许它应该是这样的:
...
return client.Get(p);
...

_facebookHelper 是否确实使用了 Mock 对象?在测试期间,它应该是 IFacebookHelperProxy 类型或类似类型。

编辑:

问题在于你试图跨程序集公开匿名类型,因为你只能在创建它们的程序集内使用匿名类型。

所以,不要使用

public class DynTestProxy:IDynTest
{
    public dynamic GetData()
    {
        return (dynamic) new { DynamicProperty = "From Unit Test" };
    }
}

您应该使用一个 ExpandoObject

public class DynTestProxy:IDynTest
{
    public dynamic GetData()
    {
        dynamic r = new ExpandoObject();
        r.DynamicProperty = "From Unit Test";
        return r;
    }
}

或者使用InternalsVisibleTo属性。更多信息请参见此处。此外,这个问题可能会对您有所帮助。


是的,应该返回client.Get(p),但那不是我遇到的问题。最终我遇到的问题似乎是由于MOQ引起的。我重新做了很多工作,并创建了自己的Facebook连接器,它返回一个JObject类型,这个方法运行良好。 - Paul Johnson
奇怪的是,正如我发布的示例所示,Moqdynamic不应该有任何问题。 - sloth
我刚刚稍微编辑了一下我的帖子。是的,这根本不是MOQ,只是关于动态类型和不同程序集的一些奇怪问题。通常我会为这样的事情使用强类型转换,唯一遇到这个问题的原因是由于一个返回动态类型的Facebook Nuget。实际上,我之前从未使用过动态类型 :) - Paul Johnson
“问题在于您试图跨程序集边界公开匿名类型”,这让我大开眼界!谢谢。 - Bas Slagter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接