From 645d9a86489600a47d49564032e1915938c19a0b Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Sun, 21 Apr 2024 20:52:48 -0400 Subject: [PATCH] Refine Matcher Use --- example/MatcherTests.cs | 75 +++++++++++++++++++ example/Random.cs | 22 ------ example/{UnitTest1.cs => SimpleTests.cs} | 29 ++----- .../Emitter/SetupActionEmitter.cs | 15 +++- .../Parser/SetupActionParser.cs | 2 +- .../SetupArguments/SetupArgumentParser.cs | 2 +- .../Internals/SingleUseCallHandler.cs | 19 ++++- 7 files changed, 114 insertions(+), 50 deletions(-) create mode 100644 example/MatcherTests.cs delete mode 100644 example/Random.cs rename example/{UnitTest1.cs => SimpleTests.cs} (76%) diff --git a/example/MatcherTests.cs b/example/MatcherTests.cs new file mode 100644 index 0000000..e9f2bd3 --- /dev/null +++ b/example/MatcherTests.cs @@ -0,0 +1,75 @@ +using Pretender; + +namespace Example.Tests; + +public class MatcherTests +{ + [Fact] + public void OneAnyMatcher_OneAnonymousMatcher() + { + var testInterfacePretend = Pretend.That(); + + testInterfacePretend + .Setup(i => i.Test(It.IsAny(), It.Is(s => s == "Hi"))) + .Returns(1); + + var testInterface = testInterfacePretend.Create(); + + var returnValue = testInterface.Test("Yo", "Hi"); + Assert.Equal(1, returnValue); + } + + [Fact] + public void TwoAnonymousMatchers() + { + var testInterfacePretend = Pretend.That(); + + testInterfacePretend + .Setup(i => i.Test(It.Is(s => s == "Yo"), It.Is(s => s == "Hi"))) + .Returns(1); + + var testInterface = testInterfacePretend.Create(); + + var returnValue = testInterface.Test("Yo", "Hi"); + Assert.Equal(1, returnValue); + } + + [Fact] + public void AnonymousMatcherThatCapturesLocal() + { + var testInterfacePretend = Pretend.That(); + + string local = "Yo"; + + testInterfacePretend + .Setup(i => i.Test(It.Is(s => s == local), It.Is(s => s == "Hi"))) + .Returns(1); + + var testInterface = testInterfacePretend.Create(); + + var returnValue = testInterface.Test("Yo", "Hi"); + Assert.Equal(1, returnValue); + } + + public string TestProperty { get; set; } = "Yo"; + + [Fact] + public void AnonymousMatcherThatCapturesProperty() + { + var testInterfacePretend = Pretend.That(); + + testInterfacePretend + .Setup(i => i.Test(It.Is(s => s == TestProperty), It.Is(s => s == "Hi"))) + .Returns(1); + + var testInterface = testInterfacePretend.Create(); + + var returnValue = testInterface.Test("Yo", "Hi"); + Assert.Equal(1, returnValue); + } +} + +public interface ITestInterface +{ + int Test(string arg1, string arg2); +} diff --git a/example/Random.cs b/example/Random.cs deleted file mode 100644 index 274ef9b..0000000 --- a/example/Random.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Example; - -using Pretender; - -namespace MyTest; - -public class TestClass -{ - public TestClass() - { - var pretend = Pretend.That(); - pretend.Setup(i => i.Greeting("John", 12)); - } -} - -/// -/// My Information -/// -//public interface IInterface -//{ -// string Greeting(string name, int hello); -//} \ No newline at end of file diff --git a/example/UnitTest1.cs b/example/SimpleTests.cs similarity index 76% rename from example/UnitTest1.cs rename to example/SimpleTests.cs index 6d72f74..de0e4e9 100644 --- a/example/UnitTest1.cs +++ b/example/SimpleTests.cs @@ -1,11 +1,11 @@ using Pretender; -namespace Example; +namespace Example.Tests; -public class UnitTest1 +public class SimpleTests { [Fact] - public void Test1() + public void OneLiteral_OneAnyMatcher() { var pretendMyInterface = Pretend.That() .Setup(i => i.Greeting("Mike", It.IsAny())) @@ -17,7 +17,7 @@ public void Test1() } [Fact] - public async Task Test2() + public async Task OneCapturedLocal() { var pretend = Pretend.That(); @@ -37,7 +37,7 @@ public async Task Test2() } [Fact] - public void Test3() + public void OneLiteral_OneFunctionMatcher() { var pretend = Pretend.That(); @@ -52,35 +52,18 @@ public void Test3() Assert.Equal("2", response); setup.Verify(1); + setup.Verify(..2); } } public interface IMyInterface { - /// - /// Hello - /// - /// - /// Task Greeting(string? name); void Something(); } -public interface IMyOtherInterface -{ - void Greeting(); -} - -/// -/// My Information -/// public interface IInterface { string? Greeting(string name, int num); -} - -public sealed class TestClass -{ - } \ No newline at end of file diff --git a/src/Pretender.SourceGenerator/Emitter/SetupActionEmitter.cs b/src/Pretender.SourceGenerator/Emitter/SetupActionEmitter.cs index 18fc0e9..b0bb5f9 100644 --- a/src/Pretender.SourceGenerator/Emitter/SetupActionEmitter.cs +++ b/src/Pretender.SourceGenerator/Emitter/SetupActionEmitter.cs @@ -52,13 +52,24 @@ public void Emit(IndentedTextWriter writer, CancellationToken cancellationToken) if (_setupArgumentEmitters.Any(a => a.NeedsCapturer)) { // TODO: Create single use call handler - writer.WriteLine("var singleUseCallHandler = new SingleUseCallHandler();"); + if (returnType is null) + { + writer.WriteLine("var singleUseCallHandler = new SingleUseCallHandler();"); + } + else + { + writer.WriteLine($"var singleUseCallHandler = new SingleUseCallHandler<{returnType.ToFullDisplayString()}>();"); + } + writer.WriteLine($"var fake = new {_knownTypeSymbols.GetPretendName(PretendType)}(singleUseCallHandler);"); // Emit and run capturer + + writer.WriteLine(); writer.WriteLine("var listener = MatcherListener.StartListening();"); writer.WriteLine("setup.Method.Invoke(setup.Target, [fake]);"); - writer.WriteLine("listener.Dispose();"); + writer.WriteLine(); + writer.WriteLine("var capturedArguments = singleUseCallHandler.Arguments;"); writer.WriteLine(); } diff --git a/src/Pretender.SourceGenerator/Parser/SetupActionParser.cs b/src/Pretender.SourceGenerator/Parser/SetupActionParser.cs index 899d492..c975f21 100644 --- a/src/Pretender.SourceGenerator/Parser/SetupActionParser.cs +++ b/src/Pretender.SourceGenerator/Parser/SetupActionParser.cs @@ -126,7 +126,7 @@ private void TraverseOperation(IOperation operation, ImmutableArray /// **FOR INTERNAL USE ONLY** /// - public class SingleUseCallHandler : ICallHandler + public class SingleUseCallHandler : ICallHandler + { + public object?[] Arguments { get; private set; } = null!; + + /// + /// **FOR INTERNAL USE ONLY** Method signature subject to change. + /// + /// + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is only meant to be used by source generators")] + public void Handle(CallInfo callInfo) + { + Arguments = callInfo.Arguments; + callInfo.ReturnValue = default(T); + } + } + + public class SingleUserCallHandler : ICallHandler { public object?[] Arguments { get; private set; } = null!;