From bd80329ac7ea346fdd8434b7d45f780bd984b472 Mon Sep 17 00:00:00 2001 From: Gilles TOURREAU Date: Wed, 23 Oct 2024 12:10:25 +0200 Subject: [PATCH] Fix the PosInfoMoq2004 to not check the Mock instantiation with the factory lambda expression (fixes: #39). --- ...umentCannotBePassedForInterfaceAnalyzer.cs | 12 ++++++-- src/Moq.Analyzers/Moq.Analyzers.csproj | 3 +- ...tCannotBePassedForInterfaceAnalyzerTest.cs | 30 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Moq.Analyzers/Analyzers/ConstructorArgumentCannotBePassedForInterfaceAnalyzer.cs b/src/Moq.Analyzers/Analyzers/ConstructorArgumentCannotBePassedForInterfaceAnalyzer.cs index 8a31e27..b983433 100644 --- a/src/Moq.Analyzers/Analyzers/ConstructorArgumentCannotBePassedForInterfaceAnalyzer.cs +++ b/src/Moq.Analyzers/Analyzers/ConstructorArgumentCannotBePassedForInterfaceAnalyzer.cs @@ -46,6 +46,15 @@ private static void Analyze(SyntaxNodeAnalysisContext context) return; } + // Check if the mock instantiation is with a factory. + // In this case, we ignore the matching of the constructor arguments. + var constructorSymbol = context.SemanticModel.GetSymbolInfo(objectCreation, context.CancellationToken); + + if (moqSymbols.IsMockConstructorWithFactory(constructorSymbol.Symbol)) + { + return; + } + var moqExpressionAnalyzer = new MoqExpressionAnalyzer(moqSymbols, context.SemanticModel); // Check there is "new Mock()" statement. @@ -90,8 +99,7 @@ private static void Analyze(SyntaxNodeAnalysisContext context) .Select(a => a.Expression.GetLocation()) .ToArray(); - var diagnostic = Diagnostic.Create(Rule, locations[0], locations.Skip(1)); - context.ReportDiagnostic(diagnostic); + context.ReportDiagnostic(Rule, locations); return; } diff --git a/src/Moq.Analyzers/Moq.Analyzers.csproj b/src/Moq.Analyzers/Moq.Analyzers.csproj index 0d0607d..a020d58 100644 --- a/src/Moq.Analyzers/Moq.Analyzers.csproj +++ b/src/Moq.Analyzers/Moq.Analyzers.csproj @@ -21,7 +21,8 @@ - Add new rules: - PosInfoMoq2014: The delegate in the argument of the Returns() method must return a value with same type of the mocked method. - PosInfoMoq2015: The Protected().Setup() method must match the return type of the mocked method. - - Fix the PosInfoMoq1001 rule for the Mock<T> instantiation with the lambad expression to create mock object. + - Fix the PosInfoMoq1001 rule for the Mock<T> instantiation with the lambda expression to create mock instances. + - Fix the PosInfoMoq2004 rule for the Mock<T> instantiation with the lambda expression to create mock instances. 1.10.0 - Add new rules: diff --git a/tests/Moq.Analyzers.Tests/Analyzers/ConstructorArgumentCannotBePassedForInterfaceAnalyzerTest.cs b/tests/Moq.Analyzers.Tests/Analyzers/ConstructorArgumentCannotBePassedForInterfaceAnalyzerTest.cs index 40dc526..6f48b13 100644 --- a/tests/Moq.Analyzers.Tests/Analyzers/ConstructorArgumentCannotBePassedForInterfaceAnalyzerTest.cs +++ b/tests/Moq.Analyzers.Tests/Analyzers/ConstructorArgumentCannotBePassedForInterfaceAnalyzerTest.cs @@ -113,6 +113,36 @@ await Verifier.VerifyAnalyzerAsync( .WithLocation(1).WithArguments("2")); } + [Theory] + [InlineData("")] + [InlineData(", MockBehavior.Strict")] + public async Task Interface_WithFactoryLambdaExpression(string behavior) + { + var source = @" + namespace ConsoleApplication1 + { + using Moq; + + public class TestClass + { + public void TestMethod() + { + var mock1 = new Mock(() => new C()" + behavior + @"); + } + } + + public interface I + { + } + + public class C : I + { + } + }"; + + await Verifier.VerifyAnalyzerAsync(source); + } + [Fact] public async Task Class() {