4

この質問がされた場合は申し訳ありませんが、答えがどこにも見つかりませんでした。

私の問題は、そのメソッドが動的な型を返す MOQ を使用して return メソッドをモックするときです。動的時間を使用するサード パーツ ライブラリを使用しています。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" };
        }
    }
}

名前空間 MyLib、Warrior.WebUI、Warrior.Tests で示される 3 つのプロジェクトがあります。
そのままでは、テストはエラーで失敗します..「オブジェクト」には、RetTest() で発生する「DynamicProperty」の定義が含まれていません

ただし、DynTestProxy クラスを Warrior.WebUI プロジェクトに単純に移動すると、すべて正常に動作します。さまざまなアセンブリまたは何かにまたがって動的型を送信するときに問題があると思います。

4

1 に答える 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属性を使用します。詳細については、こちらをご覧ください。また、この質問はあなたにとって興味深いかもしれません。

于 2012-06-06T13:30:14.833 に答える