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

Add netstandard2.0 target #784

Merged
merged 5 commits into from
Mar 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ This release contains several **minor breaking changes**. Please review your cod
* `mock.Verify` no longer creates setups, nor will it override existing setups, as a side-effect of using a recursive expression. (@stakx, #765)
* More accurate detection of argument matchers with `SetupSet` and `VerifySet`, especially when used in fluent setup expressions or with indexers (@stakx, #767)
* `mock.Verify(expression)` error messages now contain a full listing of all invocations that occurred across all involved mocks. Setups are no longer listed, since they are completely irrelevant in the context of call verification. (@stakx, #779, #780)
* Additionally target .NET Standard 2.0 (@stakx, #780)

#### Added

Expand Down
62 changes: 33 additions & 29 deletions src/Moq/MethodCall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,26 @@ internal sealed partial class MethodCall : SetupWithOutParameterSupport
private string failMessage;
private Flags flags;
private Mock mock;
#if !NETCORE
private string originalCallerFilePath;
private int originalCallerLineNumber;
private MethodBase originalCallerMember;
#endif
private RaiseEventResponse raiseEventResponse;
private Response returnOrThrowResponse;

#if FEATURE_CALLERINFO
private string declarationSite;
#endif

public MethodCall(Mock mock, Condition condition, InvocationShape expectation)
: base(expectation)
{
this.condition = condition;
this.flags = expectation.Method.ReturnType != typeof(void) ? Flags.MethodIsNonVoid : 0;
this.mock = mock;

this.SetFileInfo();
#if FEATURE_CALLERINFO
if ((mock.Switches & Switches.CollectDiagnosticFileInfoForSetups) != 0)
{
this.declarationSite = GetUserCodeCallSite();
}
#endif
}

public string FailMessage
Expand All @@ -53,40 +57,44 @@ public string FailMessage

public override bool IsVerifiable => (this.flags & Flags.Verifiable) != 0;

[Conditional("DESKTOP")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
private void SetFileInfo()
#if FEATURE_CALLERINFO
private static string GetUserCodeCallSite()
{
#if !NETCORE
if ((this.mock.Switches & Switches.CollectDiagnosticFileInfoForSetups) == 0)
{
return;
}

try
{
var thisMethod = MethodBase.GetCurrentMethod();
var mockAssembly = Assembly.GetExecutingAssembly();
// Move 'till we're at the entry point into Moq API
var frame = new StackTrace(true)
.GetFrames()
.SkipWhile(f => f.GetMethod() != thisMethod)
.SkipWhile(f => f.GetMethod().DeclaringType == null || f.GetMethod().DeclaringType.Assembly == mockAssembly)
.FirstOrDefault();

if (frame != null)
var member = frame?.GetMethod();
if (member != null)
{
this.originalCallerLineNumber = frame.GetFileLineNumber();
this.originalCallerFilePath = Path.GetFileName(frame.GetFileName());
this.originalCallerMember = frame.GetMethod();
var declaredAt = new StringBuilder();
declaredAt.AppendNameOf(member.DeclaringType).Append('.').AppendNameOf(member, false);
var fileName = Path.GetFileName(frame.GetFileName());
if (fileName != null)
{
declaredAt.Append(" in ").Append(fileName);
var lineNumber = frame.GetFileLineNumber();
if (lineNumber != 0)
{
declaredAt.Append(": line ").Append(lineNumber);
}
}
return declaredAt.ToString();
}
}
catch
{
// Must NEVER fail, as this is a nice-to-have feature only.
}
#endif

return null;
}
#endif

public override void Execute(Invocation invocation)
{
Expand Down Expand Up @@ -351,14 +359,10 @@ public override string ToString()

message.Append(base.ToString());

#if !NETCORE
if (this.originalCallerMember != null && this.originalCallerFilePath != null && this.originalCallerLineNumber != 0)
#if FEATURE_CALLERINFO
if (this.declarationSite != null)
{
message.AppendFormat(
" ({0}() in {1}: line {2})",
this.originalCallerMember.Name,
this.originalCallerFilePath,
this.originalCallerLineNumber);
message.Append(" (").Append(this.declarationSite).Append(')');
}
#endif

Expand Down
27 changes: 5 additions & 22 deletions src/Moq/Mock.Generic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,19 @@
// All rights reserved. Licensed under the BSD 3-Clause License; see License.txt.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading;

#if FEATURE_CODEDOM
using System.CodeDom;
using Microsoft.CSharp;
#endif

using Moq.Language;
using Moq.Language.Flow;
using Moq.Properties;
using Moq.Protected;

namespace Moq
{
Expand Down Expand Up @@ -121,22 +115,11 @@ public Mock(MockBehavior behavior, params object[] args)

private static string CreateUniqueDefaultMockName()
{
var serialNumber = Interlocked.Increment(ref serialNumberCounter).ToString("x8");

string typeName = typeof (T).FullName;

#if FEATURE_CODEDOM
if (typeof (T).IsGenericType)
{
using (var provider = new CSharpCodeProvider())
{
var typeRef = new CodeTypeReference(typeof(T));
typeName = provider.GetTypeOutput(typeRef);
}
}
#endif
var serialNumber = Interlocked.Increment(ref serialNumberCounter);

return "Mock<" + typeName + ":" + serialNumber + ">";
var name = new StringBuilder();
name.Append("Mock<").AppendNameOf(typeof(T)).Append(':').Append(serialNumber).Append('>');
return name.ToString();
}

private void CheckParameters()
Expand Down
12 changes: 9 additions & 3 deletions src/Moq/Moq.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Import Project="$(BuildDirectory)SourceLink.props" />

<PropertyGroup>
<TargetFrameworks>net45;netstandard1.3</TargetFrameworks>
<TargetFrameworks>net45;netstandard1.3;netstandard2.0</TargetFrameworks>
<AssemblyName>Moq</AssemblyName>
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
Expand All @@ -29,10 +29,13 @@
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' ">
<DefineConstants>$(DefineConstants);DESKTOP;FEATURE_CAS;FEATURE_CODEDOM;FEATURE_COM;FEATURE_SERIALIZATION</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_CALLERINFO;FEATURE_CAS;FEATURE_COM;FEATURE_SERIALIZATION</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<DefineConstants>$(DefineConstants);FEATURE_CALLERINFO;FEATURE_SERIALIZATION</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
<DefineConstants>$(DefineConstants)</DefineConstants>
</PropertyGroup>

<ItemGroup>
Expand All @@ -51,6 +54,9 @@
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.5.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
Expand Down
8 changes: 8 additions & 0 deletions src/Moq/Moq.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
<dependency id="System.Reflection.TypeExtensions" version="4.5.1" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.1" />
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="Castle.Core" version="4.3.1" />
<dependency id="System.Reflection.Emit" version="4.3.0" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.1" />
</group>
</dependencies>
</metadata>
<files>
Expand All @@ -34,5 +39,8 @@
<file src="bin\$configuration$\netstandard1.3\Moq.dll" target="lib\netstandard1.3" />
<file src="bin\$configuration$\netstandard1.3\Moq.pdb" target="lib\netstandard1.3" />
<file src="bin\$configuration$\netstandard1.3\Moq.xml" target="lib\netstandard1.3" />
<file src="bin\$configuration$\netstandard2.0\Moq.dll" target="lib\netstandard2.0" />
<file src="bin\$configuration$\netstandard2.0\Moq.pdb" target="lib\netstandard2.0" />
<file src="bin\$configuration$\netstandard2.0\Moq.xml" target="lib\netstandard2.0" />
</files>
</package>
2 changes: 1 addition & 1 deletion src/Moq/StringBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static StringBuilder AppendIndented(this StringBuilder stringBuilder, str
return stringBuilder;
}

public static StringBuilder AppendNameOf(this StringBuilder stringBuilder, MethodInfo method, bool includeGenericArgumentList)
public static StringBuilder AppendNameOf(this StringBuilder stringBuilder, MethodBase method, bool includeGenericArgumentList)
{
stringBuilder.Append(method.Name);

Expand Down
13 changes: 5 additions & 8 deletions tests/Moq.Tests/MockFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
#if NETCORE
using System.Reflection;
#endif

using Xunit;

#if FEATURE_SERIALIZATION
using System.Runtime.Serialization;
#endif

using Xunit;

namespace Moq.Tests
{
public class MockFixture
Expand Down Expand Up @@ -50,19 +49,17 @@ public void HasADefaultNameThatIncludesItsTypeAndThatItsAMock()
{
var mock = new Mock<IComparable>();

Assert.Contains("System.IComparable", mock.ToString());
Assert.Contains("IComparable", mock.ToString());
Assert.Contains("mock", mock.ToString().ToLower());
}

#if FEATURE_CODEDOM
[Fact]
public void HasADefaultNameThatIncludesItsGenericParameters()
{
var mock = new Mock<Dictionary<int, string>>();

Assert.Contains("System.Collections.Generic.Dictionary<int, string>", mock.ToString());
Assert.Contains("Dictionary<int, string>", mock.ToString());
}
#endif

[Fact]
public void PassesItsNameOnToTheResultingMockObjectWhenMockingInterfaces()
Expand Down
18 changes: 12 additions & 6 deletions tests/Moq.Tests/Moq.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net46' ">
<DefineConstants>$(DefineConstants);DESKTOP;FEATURE_CAS;FEATURE_CODEDOM;FEATURE_COM;FEATURE_SERIALIZATION</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_CALLERINFO;FEATURE_CAS;FEATURE_COM;FEATURE_EF;FEATURE_SERIALIZATION;FEATURE_SYSTEM_WEB;FEATURE_SYSTEM_WINDOWS_FORMS</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
<DefineConstants>$(DefineConstants)</DefineConstants>
</PropertyGroup>

<ItemGroup>
Expand All @@ -27,14 +27,20 @@
<ProjectReference Include="..\..\src\Moq\Moq.csproj" />
<ProjectReference Include="..\Moq.Tests.FSharpTypes\Moq.Tests.FSharpTypes.fsproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<PackageReference Include="EntityFramework" Version="6.2.0" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<ItemGroup Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch('$(DefineConstants)', 'FEATURE_COM'))">
<Reference Include="Moq.Tests.ComTypes">
<HintPath>..\Moq.Tests.ComTypes\Moq.Tests.ComTypes.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch('$(DefineConstants)', 'FEATURE_EF'))">
<PackageReference Include="EntityFramework" Version="6.2.0" />
</ItemGroup>
<ItemGroup Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch('$(DefineConstants)', 'FEATURE_SYSTEM_WEB'))">
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch('$(DefineConstants)', 'FEATURE_SYSTEM_WINDOWS_FORMS'))">
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">
<PackageReference Include="System.Collections.Specialized" Version="4.3.0" />
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
Expand Down
Loading