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

Pau*_*son 3 c# return moq mocking dynamic-typing

如果有人提出这个问题但我无法在任何地方找到答案.

我的问题是在使用MOQ模拟返回方法时,该方法返回动态类型.我正在使用第三部分库,它使用动态时间.MOQ似乎将动态类型转换为对象.

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

模拟帮助器中的方法.

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

来自控制器的代码使用模拟结果.

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

基本上,MOQ返回了一个动态类型的对象,需要将其作为某种东西进行渲染.

有谁知道如何解决这个问题?我假设它可能是因为MOQ没有在.NET 4中编码因此不支持动态类型?

编辑

实际上我不认为这是一个MOQ问题,因为我创建了自己的模拟类,但仍然遇到了同样的问题.我是动态类型的新手,但不知道发生了什么.

编辑2 - 部分回答..问题毕竟与MOQ无关

实际上问题似乎是由于在不同的程序集中创建了动态类型.虽然我使用JObject类型解决了我最初的问题,但我还是想弄明白这一点.

namespace MyLib.Tools
{
    public interface IDynTest
    {
        dynamic GetData();
    }
}
Run Code Online (Sandbox Code Playgroud)
namespace MyLib.Tools
{
    public class DynTest : Effect.Tools.IDynTest
    {
        public dynamic GetData() {
            return new { DynamicProperty = "hello" };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
namespace Warrior.Tests
{
    public class DynTestProxy:IDynTest
    {
        public dynamic GetData()
        {
            return (dynamic) new { DynamicProperty = "From Unit Test" };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Namespace MyLib,Warrior.WebUI和Warrior.Tests指示了3个项目.
因为它是测试失败并出现错误..'object'不包含在RetTest()上发生的'DynamicProperty'的定义

但是,如果我只是将DynTestProxy类移动到Warrior.WebUI项目中,一切正常.我猜测在不同程序集或其他东西发送动态类型时会出现问题.

slo*_*oth 7

我做了一个快速测试:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这工作正常.我这里没有看到问题.

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

看看你发布的方法:

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

也许它应该是:

...
return client.Get(p);
...
Run Code Online (Sandbox Code Playgroud)

难道_facebookHelper真的使用Mock对象?IFacebookHelperProxy在测试过程中它应该是类型或类似的东西.

编辑:

问题是您尝试跨程序集边界公开匿名类型,因为您只能在创建它们的程序集中使用匿名类型.

而不是

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

你应该使用ExpandoObject:

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

或使用InternalsVisibleTo属性.有关更多信息,请参见此处 另外这个问题可能对你有意思.