Cannot use moles to mock the MVC framework

2019-04-30 00:55发布

问题:

I am trying to generate moles for the System.Web.Mvc DLL version 3, but I get the following error:

 Moles : info : metadata : loading C:\TFS.as12.Projects\Project X\Main\Source\3rdPartyComponents\MVC3\System.Web.Mvc.dll
    Moles : info : compilation : output assembly name: System.Web.Mvc.Moles
Moles : warning : metadata : failed to load module System.Web.Mvc.dll:
Moles : warning : metadata : Inheritance security rules violated by type: 'System.Web.Mvc.CompareAttribute'. Derived types must either match the security accessibility of the base type or be less accessible.
Moles : warning : metadata : Inheritance security rules violated by type: 'System.Web.Mvc.RemoteAttribute'. Derived types must either match the security accessibility of the base type or be less accessible.
Moles : error : code : assembly contains no types or failed to load properly
  00:00:00.53> moles generator 1 errors, 3 warnings

    Moles compilation FAILED - 6,18794176354816s
C:\Program Files (x86)\Microsoft Moles\bin\Microsoft.Moles.targets(79,5): error MSB3073: The command ""C:\Program Files (x86)\Microsoft Moles\bin\moles.exe" @"C:\TFS.as12.Projects\Project X\Main\Source\X.Web\X.Web.Base.Mvc.UnitTest\obj\Debug\Moles\moles.args"" exited with code -1002.

I have seen more questions about this on the Microsoft forums, but never an answer. Does anyone have a solution?

回答1:

This is related to a known issue. If you have your heart set on using Moles with MVC3, you can do the following (I have done this):

  1. Download the MVC3 source code.
  2. Remove [SecurityTransparent] from Properties/AssemblyInfo.cs
  3. Extract the MS public key from the real MVC dll using sn.exe: "sn -e System.Web.Mvc.dll ms_public_key.snk"
  4. Tell VS to use that public key when signing your fake MVC dll (you can do this under project properties, signing). Make sure you check the "delay sign only" box.
  5. Build. Now you have a fake MVC dll that is signed with the MS public key. But you can't use it for anything because it won't pass muster with signing verification.
  6. Use sn.exe again to register a skip-verification for your fake dll: "sn -Vr System.Web.Mvc.dll" <--- this needs to be your fake one
  7. GAC your fake one with gacutil.exe: "gacutil -if System.Web.Mvc.dll" <--- again, the fake one
  8. Run moles. I strongly recommend you stub/mole the entire dll because you're not going to want to have to do this again.
  9. Remove the skip-verification: "sn -Vu System.Web.Mvc.dll" <--- the fake one
  10. Restore the real dll: "gacutil -if System.Web.Mvc.dll" <--- the real one
  11. Delete your evil fake MVC dll lest someone accidently use it.

The System.Web.Mvc.Moles.dll you generated in step 8 will reference the real MVC dll, thanks to the public key switching you did. You can use it to stub/mole MVC classes to your heart's content.



回答2:

You could try excluding problematic types:

<Moles ...
   <StubGeneration ...
       <Types>
          <Remove TypeName="System.Web.Mvc.CompareAttribute" />
          <Remove TypeName="System.Web.Mvc.RemoteAttribute" />
       </Types>
   <MoleGeneration>
       <Types>
          <Remove TypeName="System.Web.Mvc.CompareAttribute" />
          <Remove TypeName="System.Web.Mvc.RemoteAttribute" />
       </Types>
   </MoleGeneration>


回答3:

To add to what @bhamlin mentioned, in step #2, I also had to make the following changes in AssemblyInfo.cs to generate moles:

Modify

[assembly: AllowPartiallyTrustedCallers]

to

[assembly: AllowPartiallyTrustedCallers(PartialTrustVisibilityLevel = PartialTrustVisibilityLevel.NotVisibleByDefault)]

as this is what's defined in System.ComponentModel.DataAnnotations.dll

Derived types must either match the security accessibility of the base type or be less accessible

Base class for CompareAttribute, which is ValidationAttribute, is in this assembly.