From fd7b5f0f0f6121cd1ef8fe711a5360e1099554b0 Mon Sep 17 00:00:00 2001 From: JKorf Date: Tue, 23 Jul 2024 16:58:10 +0200 Subject: [PATCH] Added RestIntergrationTest base class for running integration tests --- .../Testing/RestIntergrationTest.cs | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 CryptoExchange.Net/Testing/RestIntergrationTest.cs diff --git a/CryptoExchange.Net/Testing/RestIntergrationTest.cs b/CryptoExchange.Net/Testing/RestIntergrationTest.cs new file mode 100644 index 0000000..bb2fe69 --- /dev/null +++ b/CryptoExchange.Net/Testing/RestIntergrationTest.cs @@ -0,0 +1,100 @@ +using CryptoExchange.Net.Objects; +using Microsoft.Extensions.Logging; +using System; +using System.Diagnostics; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.Testing +{ + /// + /// Base class for executing REST API integration tests + /// + /// Client type + public abstract class RestIntergrationTest + { + /// + /// Get a client instance + /// + /// + /// + public abstract TClient GetClient(ILoggerFactory loggerFactory); + + /// + /// Whether the test should be run. By default integration tests aren't executed, can be set to true to force execution. + /// + public virtual bool Run { get; set; } + + /// + /// Whether API credentials are provided and thus authenticated calls can be executed. Should be set in the GetClient implementation. + /// + public bool Authenticated { get; set; } + + /// + /// Create a client + /// + /// + protected TClient CreateClient() + { + var fact = new LoggerFactory(); + fact.AddProvider(new TraceLoggerProvider()); + return GetClient(fact); + } + + /// + /// Check if integration tests should be executed + /// + /// + protected bool ShouldRun() + { + var integrationTests = Environment.GetEnvironmentVariable("INTEGRATION"); + if (!Run && integrationTests != "1") + return false; + + return true; + } + + /// + /// Execute a REST endpoint call and check for any errors or warnings. + /// + /// Type of response + /// The call expression + /// Whether this is an authenticated request + public async Task RunAndCheckResult(Expression>>> expression, bool authRequest) + { + if (!ShouldRun()) + return; + + var client = CreateClient(); + + var expressionBody = (MethodCallExpression)expression.Body; + if (authRequest && !Authenticated) + { + Debug.WriteLine($"Skipping {expressionBody.Method.Name}, not authenticated"); + return; + } + + var listener = new EnumValueTraceListener(); + Trace.Listeners.Add(listener); + + WebCallResult result; + try + { + result = await expression.Compile().Invoke(client).ConfigureAwait(false); + } + catch (Exception ex) + { + throw new Exception($"Method {expressionBody.Method.Name} threw an exception: " + ex.ToLogString()); + } + finally + { + Trace.Listeners.Remove(listener); + } + + if (!result.Success) + throw new Exception($"Method {expressionBody.Method.Name} returned error: " + result.Error); + + Debug.WriteLine($"{expressionBody.Method.Name} {result}"); + } + } +}