Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MissingMethodException / "Method not found" after update to Moq 4.8.0 #566

Closed
JHotterbeekxBannerconnect opened this issue Jan 3, 2018 · 63 comments
Assignees

Comments

@JHotterbeekxBannerconnect

Hi,

Today I've tried updating the NuGet package from 4.7.145.0 to 4.8.0.0 and I'm running into an issue with a specific test case failing now on a strange error message. To give you some context, in our tests we create a HttpActionContext to test our authentication. This is native .net functionality. I've isolated the issue to the following code:

[Test]
public void OnActionExecuting_ShouldFillMarketInSession() {
  var fakeActionContext = _CreateFakeHttpActionContext();
}

private HttpActionContext _CreateFakeHttpActionContext() {
  return new HttpActionContext(null, new ReflectedHttpActionDescriptor()) {
    Response = new HttpResponseMessage(HttpStatusCode.OK)
  };
}

When running this test, it fails with the following error:

System.MissingMethodException : Method not found: 'Void System.Web.Http.Controllers.HttpActionContext.set_Response(System.Net.Http.HttpResponseMessage)'.
at SMP.Api.Test.Filter.MoqTest._CreateFakeHttpActionContext()
at SMP.Api.Test.Filter.MoqTest.OnActionExecuting_ShouldFillMarketInSession() in C:\Projects\Athena\Athena\SMP.Api.Test\Filter\MoqTest.cs:line 14

Could you help me figure out what is wrong, or fix this if it is an actual bug?

Thanks,
John

@stakx
Copy link
Contributor

stakx commented Jan 3, 2018

Hi @JHotterbeekxBannerconnect and thanks for reporting. Unfortunately, I do not see anything related to Moq in your example code, so I have to wonder whether your issue is even related to Moq at all.

Could you please provide a short but complete code example that demonstrates this issue, and shows how Moq is involved? (Otherwise I'll close this issue in a couple of days' time.) Thank you!

(Btw. MissingMethodExceptions usually indicate that you have old DLLs lurking around somewhere that are not binary-compatible with the version against which your code was compiled. Try deleting your project's obj and bin folders, your test runner's cache (if applicable), and possibly also your project's or user profile's NuGet package cache.)

@willykc
Copy link

willykc commented Jan 3, 2018

Hi, I think I'm seeing the same problem. Out of 405 tests using Moq, 16 started failing after upgrading to Moq 4.8.0 with exception "System.MissingMethodException: Method not found". It seems to be related to the "System.Net.Http" namespace since all the "missing methods" in the failing tests have types from that namespace in their signature (eg. "System.Net.Http.HttpResponseMessage").

@stakx
Copy link
Contributor

stakx commented Jan 3, 2018

@JHotterbeekxBannerconnect, @willykc: Could it be that you updated not just Moq, but any other Microsoft ASP.NET packages at the same time without noticing it? Because quite frankly, Moq has no dependency on, nor any special logic related to, any System.Net.Http.* types. I don't see how this issue could be caused by Moq, especially when the MissingMethodException gets triggered in a piece of code that doesn't even involve Moq.

@JHotterbeekxBannerconnect
Copy link
Author

We've updated several packages, but saw tests failing. So I reverted everything and updated one by one, everything keeps working until the last package is updated, which is Moq. But I'm going to try cleaning old DLL's and cache and see what that does, and if it still doesn't work try a new solution to reproduce this.

@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

@JHotterbeekxBannerconnect: That's truly strange. Until you have repro code ready to share, could you perhaps give the following information:

  • What version of Visual Studio are you working with?
  • What exact framework / platform are your projects targeting?
  • What NuGet packages (including version numbers) are your projects referencing?
  • Are you using <PackageReference>s or a NuGet packages.config?
  • Are there any assembly binding redirects in your App.config or Web.config? If so, what do they look like?
  • Is there a <AutoGenerateBindingRedirects> element in your root project file? If so, what is its value?

@JHotterbeekxBannerconnect
Copy link
Author

@stakx I've been able to reproduce it in a simple test project:
Working.without.Moq.zip

When you open this (in VS 2017) you'll see that there is one single test in there. This runs without any issues. Now try adding through NuGet, you'll see that the test fails.

I've found something more interesting, when updating to the latest version of Moq through NuGet, another package seems to come along called System.Threading.Tasks.Extensions.4.4.0. This is the one that seems to be causing the error, because if I remove this as reference from the included test project, the test will succeed again.

The other info you requested (for the test solution):

  • VS 2017 Professional 15.5.2 / .net v 4.7.02556
  • Any CPI
  • Just Moq 4.8.0
  • packages.config
  • None

Hopefully this is enough for you to reproduce it.

@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

Thanks a lot for the test solution, and the analysis you've done already! I can now reproduce this issue.

(One problem I noticed before I could even run your tests is that your project is a missing System.Web.Http assembly. I've resolved this one by installing the Microsoft.AspNet.WebApi.Core package.)

I'll now try to find the precise cause of this.

@stakx stakx removed the needs-repro label Jan 4, 2018
@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

OK, seems you're affected by the problem described in dotnet/standard#481, and adding the following to your MoqTests.csproj file appears to resolve the issue:

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

(PS: Alternatively, update your project file(s) to the new SDK format, which should already implicitly include the above properties.)

The problem indeed gets triggered by System.Threading.Tasks.Extensions package (which Moq references because of ValueTask<TResult>). Note that it does not target the full .NET Framework, only .NET Standard. Referencing a .NET Standard assembly from a .NET Framework project used to not work, but support for doing just that was added in .NET 4.6.1. Unfortunately, it's a pretty flaky feature and it sometimes requires assembly binding redirects (which your test project doesn't have).

Please see the issue referenced above for details.

@JHotterbeekxBannerconnect
Copy link
Author

@stakx Thanks a lot for the help and explanation! I've added the properties to the solution and the tests run without any issue now. Seems like something that more people could run into, maybe this should be put in the wiki somewhere?

@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

@JHotterbeekxBannerconnect - I agree that this situation needs to be improved. I'm currently looking into Moq's reference of the System.Threading.Tasks.Extensions package (which was added in 2194e5f). It doesn't seem right that this package is referenced at all by the net45 target, as this framework version didn't yet allow references to .NET Standard assemblies. And then there's that issue I linked to to deal with.

Adding a warning to the wiki would be a start... would you like to do this?

Short of temporarily removing ValueTask<TResult> support in Moq for the full .NET Framework, I'm not sure how to cleanly resolve this problem. @AdamDotNet — you added the package reference to System.Threading.Tasks.Extensions to Moq a while ago. Do you by chance know how to properly deal with this kind of problem (cross-target assembly references)?

I'm also still not sure yet why just referencing that assembly caused the issue (note that your test doesn't make use of it).

@JHotterbeekxBannerconnect
Copy link
Author

@stakx I've added it as a FAQ to the wiki, referencing to the .net standard issue and this issue. Great that you'll look in to this, I agree that it feels weird that this issue is being caused, and even stranger without actually using anything from the reference.

@willykc
Copy link

willykc commented Jan 4, 2018

Hi @stakx, thanks a lot for the solution. After adding the property group to my test project file, all the failing tests are now passing.

I'm not sure if this could help but an idea would be to add a .props file including the property group to the Moq NuGet package like so: https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package#including-msbuild-props-and-targets-in-a-package

@JHotterbeekxBannerconnect
Copy link
Author

@stakx It seems that the adding of a .net standard reference was also causing issues on our TeamCity servers, which we had to resolve as well by updating the build tools and adding .net Core support. Just telling you because this could become an issue for more people.

@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

@JHotterbeekxBannerconnect, thanks a lot for setting up the FAQ! It's great to have such a resource that we can direct people to. 👍

@willykc, that's good to know—thanks for the link. However, I don't feel too comfortable about Moq influencing the build process behind the user's back. Moq is just a library and just one out of many possible dependencies a project might have. Imagine the potential complications if every dependency secretly modified your build. Some people might not actually want to have assembly binding redirects generated automatically.

I believe the problem should be solved at the source, if possible. And I suspect it's that the build process picks the wrong assembly version from the System.Threading.Tasks.Extensions package (starting with .NET 4.6.1, it can pick either the .NET Standard assembly, or the Portable Class Library assembly, the latter of which is probably the right one to pick). I'll try to figure out the exact circumstances under which this problem appears.

If all else fails, I'm quite ready to temporarily remove ValueTask<TResult> support from Moq so people don't run into this while we find a permanent solution.

I'll keep you updated!

@AdamDotNet
Copy link
Contributor

AdamDotNet commented Jan 4, 2018

@stakx
My understanding is that, it's not .Net 4.6.1 that enabled referencing .Net Standard libraries, it's that .Net 4.6.1 was the lowest version that works with .Net Standard 2.0 specifically. The tooling (VS) helps you reference .Net Standard libraries, not necessarily the Framework you are targeting.

The System.Threading.Tasks.Extensions NuGet has a dependency on .Net Standard 1.0, the lowest common denominator. Microsoft's documentation on .Net Standard states that a 1.0 library is compatible with .Net Framework 4.5. Therefore, it shouldn't be a problem to have the net45 TFM reference the System.Threading.Tasks.Extensions NuGet. Visual Studio / NuGet.exe should pick up the "most correct" version of the NuGet when multiple targets are available.

However, it is possible to only reference the NuGet on a specific TFM, and then #if out the relevant code if that's what you want. In fact, the Moq CSProj already does that.

For what it's worth, I just tried the following sample code on a .Net 4.5 console app without any compilation, or runtime issues; using VS 2017 15.5.2.

using Moq;
using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    public interface IFoo
    {
        ValueTask<string> Bar();
    }

    class Program
    {
        static async Task Main(string[] args)
        {
            Mock<IFoo> mock = new Mock<IFoo>();
            mock.Setup(m => m.Bar()).ReturnsAsync("Hello world");

            string bar = await mock.Object.Bar();
            Console.WriteLine(bar);
        }
    }
}

Does this answer your questions?

PS. I definitely have felt the pain of .Net Standard in .Net Framework :(

@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

Let me summarize my findings regarding MissingMethodExceptions in Moq 4.8.0. Below, you'll find:

  1. a very minimal test project which reproduces the issue;
  2. an explanation of what exactly triggers it; and
  3. a description of how to resolve this issue.

(I originally wanted to include a rant about .NET Core, .NET Standard, and NuGet having put us back firmly in DLL hell, and about the continually sorry state of .NET tooling surrounding those three; but anyone working with .NET who hasn't lived under a rock in the past few years probably knows that already, so I've edited it out. 😜)

1. Test project that reproduces a MissingMethodException:

Download it here: MinimalRepro.zip (1.4 KB).

minimalrepro

Please note:

  • Does not reference Moq. Because Moq isn't actually to blame. 😎
  • There is a warning about an assembly version conflict, and a hint about adding a <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> property to the project file. Depending on the way how you set up your own projects, you might or might not see something similar.

2. Why is the MissingMethodException occurring?

  • The test project targets the full .NET Framework (4.6.1, but the exact version is perhaps unimportant).
  • We are referencing the System.Threading.Tasks.Extensions NuGet package, presumably because we'd like to use ValueTask<> somewhere in our project.
  • That package does not explicitly have an assembly for that target. Among other targets, it supports Portable Class Library profile 259 (which includes .NET 4.5) and .NET Standard 1.0. Visual Studio / MSBuild will pick the latter.
  • Referencing a .NET Standard assembly (System.Threading.Tasks.Extensions) from a .NET Framework project (MinimalRepro) implies that during a build, a whole lot of supporting .NET Standard assemblies will be copied to the output directory—regardless of whether we actually use the .NET Standard library or not. Because of that copying, our MinimalRepro's output directory will now have a .NET Standard System.Net.Http assembly, version 4.2.0.0.
  • The Microsoft.AspNet.WebApi.Core NuGet package however references the target framework's System.Net.Http version 4.0.0.0 (against which it was compiled).
  • Our own code references stuff from both System.Net.Http version 4.2.0.0 (HttpResponseMessage) and from Microsoft.AspNet.WebApi.Core (HttpActionContext).
  • Thus both versions 4.0.0.0 and 4.2.0.0 are referenced and we have a version conflict which will eventually surface as the MissingMethodException.

My personal conclusion is that System.Net.Http or some of the ASP.NET assemblies are versioned incorrectly. aspnet/Hosting#926 (comment) hints at the same thing ("...some of the ongoing issues with the System.Net.Http packages...").

3. How can I resolve this problem?

As mentioned above, try adding this to your .csproj or .vbproj project file:

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

(This shouldn't be necessary if you're using the new SDK project file format, so you can also just convert to that instead.)

@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

And finally... 🥁

4. What can be done at Moq's end?

  1. What I would like to do first is... nothing, for these reasons:

    • I'd like to see how many people actually run into this problem.
    • I'd like to see whether this problem occurs mostly within the context of ASP.NET. This would indicate that the ASP.NET folks version their assemblies incorrectly. If, however, the problem happens in a lot of different scenarios, then the tooling would be to blame.
  2. l'll direct the first few people at the FAQ set up by @JHotterbeekxBannerconnect.

  3. Beyond that, if more complaints keep rolling in, I might remove support for ValueTask<> and ValueTuple<> from Moq's net45 target. It's pretty much the only possible fix until enough time has passed for people to upgrade their tools and projects to a working combination of NuGet / MSBuild / VS.

I am open to suggestions how to resolve this in a better way.

@AdamDotNet
Copy link
Contributor

@stakx - I think for now your suggestion of wait and see a little longer probably best. The "holy grail" of .Net Standard sounded really cool until it all fell apart in actual use (in .Net Framework). System.Net.Http is probably the biggest offender, as you've found out. I can't find the war story that came to mind, but it was bad...

A possible solution is to create a Moq.Extensions NuGet. Then treats like ValueTask can be opt in rather than everyone just gets it.

@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

@AdamDotNet, thanks for this feedback, it's much appreciated. Wait a little longer it is, then!

A possible solution is to create a Moq.Extensions NuGet. Then treats like ValueTask can be opt in rather than everyone just gets it.

This is a pretty good idea! We just might do that if things don't get better soon. Thank you for suggesting it! (And, if you'd like to contribute by moving the offending bits into a separate package via a PR, please just let me know. I could signal you when the time's right.)

@AdamDotNet
Copy link
Contributor

@stakx - I could probably find time to create a new project in the Moq solution and move things over (a list of exactly what you want moved over would be appreciated, if more than just ValueTask). I'm not familiar with how you configure the build server script though.

@stakx
Copy link
Contributor

stakx commented Jan 4, 2018

@AdamDotNet - Thanks for the kind offer. If it turns out that we actually need to do this in order to resolve the issue in a clean fashion, I'd be happy to guide you. Adding another project and .nupkg to the build script should be fairly straightforward. kzu might have to set up a new API key on NuGet, not sure about that. Let's wait a bit longer and worry about the details if and when we actually get that far... agreed?

@stakx stakx changed the title Last version failing on Method not found: 'Void ...' MissingMethodException / "Method not found" after update to Moq 4.8.0 Jan 4, 2018
@stakx
Copy link
Contributor

stakx commented Jan 7, 2018

@AdamDotNet: It has belatedly occurred to me that moving all ValueTask<> and ValueTuple<> related functionality to a separate assembly / package isn't actually feasible. This would work for extension methods, such as this one:

https://github.com/moq/moq4/blob/cf10cdb0f220eb3551a8dc451ac94a6f0dc06439/Source/ReturnsExtensions.cs#L35-L38

but it wouldn't work in other cases such as here:

https://github.com/moq/moq4/blob/cf10cdb0f220eb3551a8dc451ac94a6f0dc06439/Source/LookupOrFallbackDefaultValueProvider.cs#L79-L93

without creating a module initializer (global static constructor) which C# does not support, so I fear an extension NuGet package is no way out of DLL hell. :-/

@rhyous
Copy link

rhyous commented Feb 20, 2018

Did anyone submit a bug with System.Threading.Tasks.Extensions.4.4.0 to get a fix for this issue?
Or is there a workaround for this breaking change?

Update: This workaround to manually edit the csproj to use the portalable library in the NuGet package worked for me.

    <Reference Include="System.Threading.Tasks.Extensions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>..\..\packages\System.Threading.Tasks.Extensions.4.4.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
    </Reference>

@stakx
Copy link
Contributor

stakx commented Feb 20, 2018

Did anyone submit a bug with System.Threading.Tasks.Extensions.4.4.0 to get a fix for this issue?

If any one particular package is versioned incorrectly, it would likely be System.Net.Http. But the real problem isn't with any one specific package, IMHO, but the fact that .NET 4.6.1 has been changed retroactively to support and prefer .NET Standard 2.0 over portable libraries, thereby resulting in conflicts between framework DLLs and differently-versioned .NET Standard shim DLLs being copied over to your project's output directory.

Or is there a workaround for this breaking change?

See above: #566 (comment).

This workaround to manually edit the csproj to use the portalable library in the NuGet package worked for me.

Glad you found a solution that works for you. But your manual changes will probably be overwritten next time you upgrade packages.

@rhyous
Copy link

rhyous commented Feb 20, 2018

If any one particular package is versioned incorrectly, it would likely be System.Net.Http.

I didn't think System.Net.Http was even a package involved, as it is not an installed NuGet package. However, taking into account .NET Standard shim DLLs, this makes sense. The System.Net.Http objects could be seen as completely different object in the shims.

Glad you found a solution that works for you. But your manual changes will probably be overwritten next time you upgrade packages.

Exactly why I want to follow this up. I would love for my manual changes to be overwritten AND the bug to be fixed and not notice this when the next version comes out.

@stakx
Copy link
Contributor

stakx commented Feb 20, 2018

Exactly why I want to follow this up.

I understand. Unfortunately, there's not much we can do here at the Moq project other than fixing #578.

I suggest you take this up directly with the .NET team. Like I said above, please see the issue I linked to in the comment above (dotnet/standard#481). To be very honest with you, I am really quite fed up with (and burned out a little due to) the .NET assembly versioning mess that's been going on for the past few years, so please don't count on my support. :-/

I sincerely do hope, however, that if you follow up on this, that you'll be successful in getting this through to Microsoft.

@ManfredLange
Copy link

ManfredLange commented Mar 17, 2018

Further to this: I am receiving this problem with a project in new csproj format targeting net461. Although not required, I tried it with and without the workaround adding properties AutoGenerateBindingRedirects and GenerateBindingRedirectsOutputType. No success either way. Up to now we used Moq version 4.7.8 which worked. We are trying to upgrade to Moq version 4.8.2. This also upgrades Castle.Core from version 4.0.0 to version 4.2.1.

Since we have 50+ projects with test in them switching mocking frameworks would be an expensive/risky exercise which obviously we would like to avoid.

Anyone has any other suggestion for what we could try to resolve this issue?

Update: We were using Moq to mock HttpResponseBase which is an abstract base class and at times challenging to properly mock in the first place. We have implemented our own class HttpResponseBaseMock which derives from HttpResponseBase. While we would have preferred to continue using Moq for this, it seems to be outside of the limitations of what can be done. With our explicit mock implementation we have been able to work around the problem.

@rhyous
Copy link

rhyous commented Mar 17, 2018

Did you go back to System.Threading.Tasks.Extensions.4.3.0 and make sure it is using the dll from the portable-net45+win8+wp8+wpa81 folder?

Also, just FYI, I minimized the bug, taking Moq out of the picture. The bug I submitted on this to the dotnet project was added to Milestone 5. https://github.com/dotnet/corefx/issues/27907

@ManfredLange
Copy link

@rhyous Thank you for the suggestion. We found a work around. We were using Moq to mock HttpResponseBase, HttpRequestBase and HttpContextBase. We now have our own explicit mocks in place for these. We have almost 60 projects in our solution so going back and forth between different versions of 3rd party libraries has its limitations both technically and time wise. We appreciate that it seems to a be an issue within dotnet and unrelated to Moq. In our case it appeared when we upgraded Moq. We acknowledge that it's not caused by Moq.

We continue to use Moq for almost all our mocking needs, so please keep up the excellent work on this project. Thank you!

@stakx
Copy link
Contributor

stakx commented Mar 19, 2018

@ManfredLange - Thanks for the kind words. May I suggest that you watch #605 (or rather, look out for the future Moq version where this particular issue will be resolved) if you're still interested in seeing this resolved?

It's likely that due to that issue, we'll soon add .NET Standard 2.0 as a framework target to the Moq NuGet package. I haven't carved out an exact plan yet, but adding direct support for .NET Standard 2.0 will likely mean, among other things, less NuGet package dependencies. If we update Moq's dependency on System.Threading.Tasks.Extensions to package version 4.4.0, then Moq should no longer bring in the System.Net.Http package via System.Runtime into your projects. I'm not sure if it'll work out like that in your case (you might have to update the problematic unit test projects to .NET 4.7), but it's perhaps worth a try.

(Perhaps, if you still have enough patience left to deal with this at all 😉, you could try the following already now: Upgrade the problematic unit test projects to .NET 4.7, and explicitly bring in the System.Threading.Tasks.Extensions package and pin that dependency at version 4.4.0. Afterward, bring in Moq 4.8.2. You might then need an assembly version redirect for STTE because Moq expects version 4.3.0.)

@ManfredLange
Copy link

@stakx We are migrating our projects across from net461 to netstandard2.0 / netcoreapp2.0 at the moment. For that process we believe that going to .NET 4.7, then to netstandard2.0 would be more of a sidetrack. We are happy to continue use Moq. We always knew that mocking HttpRequestBase, HttpResponseBase and HttpContextBase could be a stretch. And mocking of these classes will change with ASP.NET Core MVC again as far as we know.

We are definitely looking forward to netstandard2.0 support for Moq. :-)

@willapp
Copy link

willapp commented Mar 21, 2018

I see this is a very long thread and apologies I didn't read every single post, but I have just been bitten with what appears to be the same issue upgrading from 4.7.145.0 to 4.8.0.0, although getting a different error when running some unit tests:

System.TypeInitializationException : The type initializer for 'Moq.DefaultValueProvider' threw an exception. ----> System.IO.FileNotFoundException : Could not load file or assembly 'System.Runtime, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified. ----> System.IO.FileNotFoundException : Could not load file or assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

This is in a .Net Framework 4.5 assembly and is fixed by reverting back to 4.7.145.0 and removing the System.Threading.Tasks.Extensions nuget package so I can only assume it's related.

I know Moq is a community project but it would be nice if this breaking change had been made into a major version update so we could be a bit more confident that a minor release won't break our projects.

@stakx
Copy link
Contributor

stakx commented Mar 22, 2018

@willapp:

I know Moq is a community project but it would be nice if this breaking change had been made into a major version update so we could be a bit more confident that a minor release won't break our projects.

Given that this repository's name pretty much sets the major version in stone, I wouldn't have increased the major version for this anyway, not even with the benefit of hindsight: Adding a NuGet dependency to support a relatively minor new feature isn't a breaking change per se.

Prior to releasing Moq 4.8.0, there was no indication whatsoever that this would cause any issues for people. (Note btw. that there was a release candidate for 4.8.0. Perhaps we should have given it much more time before releasing 4.8.0 proper, but at the time I thought this pointless given the very low number of downloads and the fact that the RC generated no feedback whatsoever.)

I've said it before, and I'll say it one more time: The problem you're seeing isn't specific to Moq. There isn't anything wrong with Moq 4.8.x. per se. The problems we're having here are rather more general tooling-related issues with .NET (more precisely, with the way how NuGet and MSBuild pick the "right" package and assembly versions).

With the advent of .NET Standard, it has become possible for MSBuild to have to choose between more than one suitable assembly from those offered by a multi-targeting NuGet package. And depending on how your project is set up (target framework(s), preexisting assembly version redirects, project file format, certain MSBuild properties, etc.), MSBuild sometimes makes the wrong choice.

I'm sorry to see that this is causing Moq users some trouble, but there's simply no realistic way for Moq (or any other open-source project of comparable size) that I can see to anticipate all the possible project setups and dependencies that are out there. What needs to happen is that (1) Microsoft must continue to fix their tools to get us all out of the versioning hell .NET currently finds itself in. (VS 2017, .NET 4.7, .NET Core 2.0, and .NET Standard 2.0 are getting close to that, I think.) (2) People need to adopt these new .NET and tool versions. While that hasn't happened, (3) everyone who's affected must learn about .NET assembly versioning and how to fix versioning conflicts in their own projects.

@AdamCaviness
Copy link

First off, I totally get this is not a fault with Moq! Secondly, I want to say thanks for Moq, it is wonderful.

I've read every message here and #567 and I'm unable to workaround the issue. My test project is on framework 4.7.0. This came up when upgrading to Moq 4.8.2. (I know everyone who carefully reads all the messages already knows the basic scenario but explicit details are oh-so-important in case I'm missing something) We are using packages.config and have not moved to PackageReference yet (waiting on VS 15.7 for the migration option). There is so much noise I just want to recap the exception as well:

The type initializer for 'Moq.DefaultValueProvider' threw an exception. System.IO.FileLoadException: Could not load file or assembly 'System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040).

The referenced System.Threading.Tasks.Extensions nuget package is 4.1.1.0. The AssemblyVersion of the actual referenced dll is 4.1.1.0 (verified with JustDecompile). As @stakx has so clearly pointed out several times, the issue stems from MSBuild preferring the .netstandard2.0 assembly over the PCL/net45 assembly. @rhyous mentioned that he manually edited the project file to point to the PCL specific assembly so I tried that as well by changing that reference to portable-net45+win8+wp8+wpa81. This did not work for me either and I realize that change will get paved over when upgrading that nuget package later. Just wanted to explain that didn't work for me either.

I've tried adding the following to my test project csproj:
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
That will emit the binding redirects that VS determines to be required. I tried this with both .NET Framework 4.7.0 and 4.7.2. From my experimentation I had to also remove all my own binding redirects I had in my app.config before the output config file in the bin directory contained the auto-generated redirects. When compiling in 4.7 it put a metric ton of binding redirects in the output app.config. In 4.7.2 it only output 3 which were the three I had at the beginning. Neither 4.7 nor 4.7.2 with those options turned on solved the issue.

So I've tried .NET Framework 4.7.2, AutoGenerateBindingRedirects and GenerateBindingRedirectsOutputType, manually pointing the assembly reference in the project file to use the PCL version and all kinds of binding redirect version number changes.

I'm afraid I will have to downgrade to Moq 4.7.145 but I want to understand the problem well enough to solve it.

@stakx
Copy link
Contributor

stakx commented May 7, 2018

@AdamCaviness - people keep having problems with this... and I almost can't quite believe that tooling is indeed so broken that there's no way at all to work around this. Would it be possible for you to submit a small test project (e.g. as a ZIP file) for me to look at?

@AdamCaviness
Copy link

@stakx Because our solutions are so large I should have started with a sample project really. As I began to consider the requirements for a sample project I discovered that one of my three lower-level test projects had no app.config file and hence no binding redirects. This of course sorted it out. For the curious, I was able to keep all the project references to the assemblies pointing to netstandard2.0 instead of portable-net45+win8+wp8+wpa81. I was also able to keep my framework version at 4.7 and I didn't need 4.7.2.

@stakx
Copy link
Contributor

stakx commented May 7, 2018

@AdamCaviness - great to hear you were able to sort things out!

@ghost
Copy link

ghost commented Jun 26, 2018

We are having same issue with 4.8.3 on .net 4.6.2, have to downgrade to 4.7.145.

@stakx
Copy link
Contributor

stakx commented Jun 26, 2018

@skram-softheme ... or resolve the version conflict. It's usually very much possible. 😉

@MarcosMeli
Copy link

We solved the problem in TeamCity setting the advance setting Path to application configuration file:

image

The config file contains the binding redirect:

  <dependentAssembly>
    <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
  </dependentAssembly>

@DianaLaa
Copy link

For anyone encountering this issue in 2019. The tests ran successfully (green) on our development environment. However, they failed on the build server with

System.TypeInitializationException : The type initializer for 'Moq.DefaultValueProvider' threw an exception.
  ----> System.IO.FileLoadException : Could not load file or assembly 'System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
  ----> System.IO.FileLoadException : Could not load file or assembly 'System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
   at Moq.Mock`1..ctor(MockBehavior behavior, Object[] args)
   at SomeTest() in SomeTest.cs:line 16
--FileLoadException
   at Moq.LookupOrFallbackDefaultValueProvider..ctor()
   at Moq.EmptyDefaultValueProvider..ctor()
   at Moq.DefaultValueProvider..cctor()
--FileLoadException

Adding the Binding nodes to the PropertyGroup didn't work for me. I ended up updating System.Threading.Tasks.Extensions separately. The tests are now green on our build server as well.

@sdebruyn
Copy link

sdebruyn commented Jan 22, 2020

hi @DianaKoenraadt, could you elaborate on how you did that?

@woutermeuwis
Copy link

woutermeuwis commented Jan 27, 2020

@sdebruyn

We are having same issue with 4.8.3 on .net 4.6.2, have to downgrade to 4.7.145.

Seems to fix it

@rubixxcube
Copy link

hi @DianaKoenraadt, could you elaborate on how you did that?

I just ran into the same issue and resolved it using @DianaKoenraadt's method, basically after updating to the latest version of MOQ, go the manage nuget packages->installed tab and you will see a package for
image

If it is not the latest click the Update button on the right to update to the latest, this is what i did and after doing so everything worked. I am using VS2019.

@PawKanarek
Copy link

PawKanarek commented Jun 9, 2020

Im Using PackageReference Include="Moq" Version="4.13.1" and still encounter this problem

plioi added a commit to Ed-Fi-Alliance-OSS/Ed-Fi-ODS-AdminApp that referenced this issue Sep 18, 2020
…ding explicitly the binding redirects intended to be automated by package Microsoft.NET.Test.Sdk.

See:

devlooped/moq#566 (comment)
dotnet/standard#481
plioi added a commit to Ed-Fi-Alliance-OSS/Ed-Fi-ODS-AdminApp that referenced this issue Sep 23, 2020
…ding explicitly the binding redirects intended to be automated by package Microsoft.NET.Test.Sdk.

See:

devlooped/moq#566 (comment)
dotnet/standard#481
@devlooped devlooped locked and limited conversation to collaborators Sep 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests