【问题标题】:TypeLoadException when trying to mock IObjectSet with Moq尝试使用 Moq 模拟 IObjectSet 时出现 TypeLoadException
【发布时间】:2011-06-27 20:53:43
【问题描述】:

我有以下设置代码:

MockOf<IObjectSet<Dummy>>().Setup(c => c.AddObject(dummy)).Verifiable();
MockOf<IObjectContextWrapper>().Setup(c => c.GetObjectSet<Dummy>()).Returns(MockOf<IObjectSet<Dummy>>().Object);

其中Dummy 是一个空类定义,dummy 是一个DummyMockOf&lt;T&gt;() 是基类上的一个模拟管理功能,它基本上确保每次在一个类型上调用它时,它都返回相同的模拟实例。

包含此设置代码的测试失败并显示 TypeLoadException 和以下消息:

System.TypeLoadException : 来自程序集“DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69”的类型“IObjectSet`1Proxy389e220f10aa4d9281d0b9e136edc1d4”正在尝试实现无法访问的接口。

在 System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule 模块,Int32 tk,ObjectHandleOnStack 类型)
在 System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
在 System.Reflection.Emit.TypeBuilder.CreateType()
在 Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
在 Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(类型 proxyTargetType,Type[] 接口,ProxyGenerationOptions 选项)
在 Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(类型 interfaceToProxy,Type[] additionalInterfacesToProxy,ProxyGenerationOptions 选项,IInterceptor[] 拦截器)
在 Moq.Mock1.<InitializeInstance>b__0()
at Moq.Mock
1.InitializeInstance()
在 Moq.Mock`1.get_Object()
在 RepositoryTest.cs 中的 OddEnds.Tests.Data.EntityFramework.RepositoryTest.Delete_DeletesObjectFromObjectSet():第 43 行

我已导入System.Data.Objects 并在测试项目和被测试类所在的项目中引用了 System.Data.Entity.dll 和 Microsoft.Data.Entity.CTP.dll。构建成功,没有错误、警告或消息(除了一些与代码合同相关的...)

我该如何解决这个问题?

【问题讨论】:

    标签: moq typeloadexception


    【解决方案1】:

    我遇到了另一个我一开始无法弄清楚的案例。我正在为在我的单元测试中创建的接口做代理...

    public IDoWork
    {
        void DoWork();
    }
    

    我花了很长时间才发现问题不在于那个接口,而是单元测试本身不是公开的:

    class TestSomething // missing public keyword
    {
    
    // .. some test which tries to create a mock of the interface
    
    
        public IDoWork
        {
            void DoWork();
        }
    
    }
    

    所以,虽然 IDoWork 说它是公共的,但实际上并不是,因为它包含在私有类中。

    希望这对某人有所帮助。

    【讨论】:

      【解决方案2】:

      我发现在我的例子中,我创建了一个 Dummy 类实例,用于我的单元测试,它碰巧是私有的(因为我真的不想在外面共享测试对象)。

      我的代码是这样的:

      var mockMonitor = new Mock<ICacheMonitor<int, PrivateObject>>();
      

      其中 PrivateObject 是我的 TestClass 中的私有类定义。 因此,我的解决方法是确保 Mock 构造函数中的任何类型都是公共的。

      public class PrivateObject () {}
      

      (显然我也不会将我的公共对象称为 PrivateObject...)

      【讨论】:

      • 谢谢!这可能是非常不明显的。我确信我试图模拟的界面有问题,但我只是忘记将我的一个对象公开。
      【解决方案3】:

      您在测试中使用的任何接口或类是内部的吗?您是否使用 [assembly: InternalsVisibleTo("YourTestAssembly")] 之类的东西来编译?

      如果是这样,您还需要为 DynamicProxyGenAssembly2 添加一个,以便 Moq 为类动态生成代理。

      //goes in the AssemblyInfo.cs where the internal interfaces / classes are defined
      [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]  
      

      这是一个关于该主题的相关帖子

      http://sonofpirate.blogspot.com/2009/09/my-first-foray-into-unit-testing-with.html

      希望对你有帮助

      【讨论】:

      • 我早就停止了这方面的工作 - 我正在使用它的计算机被盗了:( - 所以我无法验证这是否是问题的解决方案。如果有人其他人来到这里并发现这很有用,请告诉我,我会将其标记为答案。
      • 今天我在谷歌上搜索这个问题已经有一段时间了。通常这应该可以工作,这也写在官方起订量网站code.google.com/p/moq/wiki/QuickStart 上。但是它对我不起作用。我猜它与moq使用的最新版本的库有关。我看到这篇文章 - stackoverflow.com/questions/4156499/… 并添加 InternalsVisibleTo Castle.Core 和 Castle.Windsor(当然还有 DynamicProxyGenAssembly2)就成功了。 PS:我在模拟一个内部接口
      • 这在 .Net Core 1.0 上的 VS2017 中确实有效。同样重要的是,它与上面一样工作,没有包含公钥。其他一些答案建议使用公钥,但这对我们的情况没有帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-11
      • 2019-07-07
      • 2021-01-18
      • 1970-01-01
      相关资源
      最近更新 更多