Skip to content

Commit

Permalink
v1.9.2 (#30)
Browse files Browse the repository at this point in the history
* Fix the PosInfoMoq1003 and PosInfoMoq2003 when using InSequence() method.
* Fix version number.
  • Loading branch information
GillesTourreau authored Aug 6, 2024
1 parent d639007 commit b0e56a2
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/github-actions-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
type: string
description: The version of the library
required: true
default: 1.9.1
default: 1.9.2
VersionSuffix:
type: string
description: The version suffix of the library (for example rc.1)
Expand Down
4 changes: 4 additions & 0 deletions src/Moq.Analyzers/Moq.Analyzers.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
<PackageProjectUrl>https://github.com/PosInformatique/PosInformatique.Moq.Analyzers</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageReleaseNotes>
1.9.2
- Fix the PosInfoMoq1003 to raise warnings when using InSequence() method.
- Fix the PosInfoMoq2003 to raise errors when using InSequence() method.

1.9.1
- Add new rules:
- PosInfoMoq2009: Mock.Of&lt;T&gt; method must be used only to mock non-sealed class
Expand Down
5 changes: 4 additions & 1 deletion src/Moq.Analyzers/MoqSymbols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,15 @@ internal sealed class MoqSymbols
private MoqSymbols(INamedTypeSymbol mockGenericClass, Compilation compilation)
{
this.mockGenericClass = mockGenericClass;

var setupConditionResultInterface = new Lazy<INamedTypeSymbol>(() => compilation.GetTypeByMetadataName("Moq.Language.ISetupConditionResult`1")!);

this.mockBehaviorEnum = new Lazy<INamedTypeSymbol>(() => compilation.GetTypeByMetadataName("Moq.MockBehavior")!);
this.isAnyTypeClass = new Lazy<INamedTypeSymbol>(() => compilation.GetTypeByMetadataName("Moq.It+IsAnyType")!);
this.isAnyMethod = new Lazy<ISymbol>(() => compilation.GetTypeByMetadataName("Moq.It")!.GetMembers("IsAny").Single());
this.verifiesInterface = new Lazy<INamedTypeSymbol>(() => compilation.GetTypeByMetadataName("Moq.Language.IVerifies")!);

this.setupMethods = new Lazy<IReadOnlyList<IMethodSymbol>>(() => mockGenericClass.GetMembers("Setup").OfType<IMethodSymbol>().ToArray());
this.setupMethods = new Lazy<IReadOnlyList<IMethodSymbol>>(() => mockGenericClass.GetMembers("Setup").Concat(setupConditionResultInterface.Value.GetMembers("Setup")).OfType<IMethodSymbol>().ToArray());
this.mockBehaviorStrictField = new Lazy<ISymbol>(() => this.mockBehaviorEnum.Value.GetMembers("Strict").First());
this.setupProtectedMethods = new Lazy<IReadOnlyList<IMethodSymbol>>(() => compilation.GetTypeByMetadataName("Moq.Protected.IProtectedMock`1")!.GetMembers("Setup").OfType<IMethodSymbol>().ToArray());
this.asMethod = new Lazy<ISymbol>(() => mockGenericClass.GetMembers("As").Single());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ namespace PosInformatique.Moq.Analyzers.Tests

public class CallBackDelegateMustMatchMockedMethodAnalyzerTest
{
[Fact]
public async Task CallBackSignatureMatch_NoDiagnosticReported()
[Theory]
[InlineData("")]
[InlineData(".InSequence(sequence)")]
public async Task CallBackSignatureMatch_NoDiagnosticReported(string sequence)
{
var source = @"
namespace ConsoleApplication1
Expand All @@ -23,31 +25,33 @@ public class TestClass
{
public void TestMethod()
{
var sequence = new MockSequence();
var mock1 = new Mock<I>();
mock1.Setup(m => m.TestMethod())
mock1" + sequence + @".Setup(m => m.TestMethod())
.Callback(() => { })
.Throws(new Exception());
mock1.Setup(m => m.TestMethod(default))
mock1" + sequence + @".Setup(m => m.TestMethod(default))
.Callback((string x) => { })
.Throws(new Exception());
mock1.Setup(m => m.TestMethod(default, default))
mock1" + sequence + @".Setup(m => m.TestMethod(default, default))
.Callback((string x, int y) => { })
.Throws(new Exception());
mock1.Setup(m => m.TestGenericMethod(1234))
mock1" + sequence + @".Setup(m => m.TestGenericMethod(1234))
.Callback((int x) => { })
.Throws(new Exception());
mock1.Setup(m => m.TestGenericMethod(It.IsAny<It.IsAnyType>()))
mock1" + sequence + @".Setup(m => m.TestGenericMethod(It.IsAny<It.IsAnyType>()))
.Callback((object x) => { })
.Throws(new Exception());
mock1.Setup(m => m.TestMethodReturn())
mock1" + sequence + @".Setup(m => m.TestMethodReturn())
.Callback(() => { })
.Returns(1234);
mock1.Setup(m => m.TestMethodReturn(default))
mock1" + sequence + @".Setup(m => m.TestMethodReturn(default))
.Callback((string x) => { })
.Returns(1234);
mock1.Setup(m => m.TestMethodReturn(default, default))
mock1" + sequence + @".Setup(m => m.TestMethodReturn(default, default))
.Callback((string x, int y) => { })
.Returns(1234);
Expand Down Expand Up @@ -80,8 +84,10 @@ public interface I
await Verifier.VerifyAnalyzerAsync(source);
}

[Fact]
public async Task CallBackSignatureNotMatch_DiagnosticReported()
[Theory]
[InlineData("")]
[InlineData(".InSequence(sequence)")]
public async Task CallBackSignatureNotMatch_DiagnosticReported(string sequence)
{
var source = @"
namespace ConsoleApplication1
Expand All @@ -93,37 +99,39 @@ public class TestClass
{
public void TestMethod()
{
var sequence = new MockSequence();
var mock1 = new Mock<I>();
mock1.Setup(m => m.TestMethod())
mock1" + sequence + @".Setup(m => m.TestMethod())
.Callback([|(int too, int much, int parameters)|] => { })
.Throws(new Exception());
mock1.Setup(m => m.TestMethod(default))
mock1" + sequence + @".Setup(m => m.TestMethod(default))
.Callback([|()|] => { })
.Throws(new Exception());
mock1.Setup(m => m.TestMethod(default))
mock1" + sequence + @".Setup(m => m.TestMethod(default))
.Callback(([|int otherType|]) => { })
.Throws(new Exception());
mock1.Setup(m => m.TestMethod(default))
mock1" + sequence + @".Setup(m => m.TestMethod(default))
.Callback([|(int too, int much, int parameters)|] => { })
.Throws(new Exception());
mock1.Setup(m => m.TestGenericMethod(1234))
mock1" + sequence + @".Setup(m => m.TestGenericMethod(1234))
.Callback(([|string x|]) => { })
.Throws(new Exception());
mock1.Setup(m => m.TestGenericMethod(It.IsAny<It.IsAnyType>()))
mock1" + sequence + @".Setup(m => m.TestGenericMethod(It.IsAny<It.IsAnyType>()))
.Callback(([|string x|]) => { })
.Throws(new Exception());
mock1.Setup(m => m.TestMethodReturn())
mock1" + sequence + @".Setup(m => m.TestMethodReturn())
.Callback([|(int too, int much, int parameters)|] => { })
.Returns(1234);
mock1.Setup(m => m.TestMethodReturn(default))
mock1" + sequence + @".Setup(m => m.TestMethodReturn(default))
.Callback([|()|] => { })
.Returns(1234);
mock1.Setup(m => m.TestMethodReturn(default))
mock1" + sequence + @".Setup(m => m.TestMethodReturn(default))
.Callback(([|int otherType|]) => { })
.Returns(1234);
mock1.Setup(m => m.TestMethodReturn(default))
mock1" + sequence + @".Setup(m => m.TestMethodReturn(default))
.Callback([|(int too, int much, int parameters)|] => { })
.Returns(1234);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ await Verifier.VerifyAnalyzerAsync(
}

[Fact]
public async Task Callback_NoDiagnosticReported()
public async Task NoCallback_DiagnosticReported_WithSequence()
{
var source = @"
namespace ConsoleApplication1
Expand All @@ -69,21 +69,72 @@ public class TestClass
{
public void TestMethod()
{
var sequence = new MockSequence();
var mock1 = new Mock<I>();
mock1.InSequence(sequence).Setup(m => m.TestMethod({|#0:It.IsAny<string>()|#0}, {|#1:It.IsAny<int>()|#1}));
mock1.InSequence(sequence).Setup(m => m.TestMethod(""Ignored"", {|#2:It.IsAny<int>()|#2}));
mock1.InSequence(sequence).Setup(m => m.TestMethod({|#3:It.IsAny<string>()|#3}, 1234));
mock1.InSequence(sequence).Setup(m => m.TestMethod({|#4:It.IsAny<string>()|#4}));
}
}
public interface I
{
void TestMethod(string a);
void TestMethod(string a, int b);
}
}";

await Verifier.VerifyAnalyzerAsync(
source,
[
new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
.WithSpan(14, 80, 14, 98).WithArguments("a"),
new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
.WithSpan(14, 100, 14, 115).WithArguments("b"),
new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
.WithSpan(15, 91, 15, 106).WithArguments("b"),
new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
.WithSpan(16, 80, 16, 98).WithArguments("a"),
new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
.WithSpan(17, 80, 17, 98).WithArguments("a"),
]);
}

[Theory]
[InlineData("")]
[InlineData(".InSequence(sequence)")]
public async Task Callback_NoDiagnosticReported(string sequence)
{
var source = @"
namespace ConsoleApplication1
{
using Moq;
using System;
public class TestClass
{
public void TestMethod()
{
var sequence = new MockSequence();
var mock1 = new Mock<I>();
mock1.Setup(m => m.TestMethod(It.IsAny<string>()))
mock1" + sequence + @".Setup(m => m.TestMethod(It.IsAny<string>()))
.Callback(() => { });
mock1.Setup(m => m.TestMethod(It.IsAny<string>(), It.IsAny<int>()))
mock1" + sequence + @".Setup(m => m.TestMethod(It.IsAny<string>(), It.IsAny<int>()))
.Callback(() => { });
mock1.Setup(m => m.TestMethod(""OK"", It.IsAny<int>()))
mock1" + sequence + @".Setup(m => m.TestMethod(""OK"", It.IsAny<int>()))
.Callback(() => { });
mock1.Setup(m => m.TestMethod(It.IsAny<string>(), 1234))
mock1" + sequence + @".Setup(m => m.TestMethod(It.IsAny<string>(), 1234))
.Callback(() => { });
var mock2 = new Mock<I>();
mock2.Setup(m => m.TestMethod());
mock2" + sequence + @".Setup(m => m.TestMethod());
var mock3 = new Mock<I>();
mock3.Setup(m => m.TestMethod(""OK"", 1234));
mock3" + sequence + @".Setup(m => m.TestMethod(""OK"", 1234));
var o = new object();
o.ToString(); // Ignored
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ private C(int a, object b, int c, System.IDisposable d)
await Verifier.VerifyAnalyzerAsync(source);
}


[Theory]
[InlineData("class")]
[InlineData("abstract class")]
Expand Down

0 comments on commit b0e56a2

Please sign in to comment.