mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-06 15:36:30 +00:00
Added unit tests, added solution, added travis build
This commit is contained in:
parent
27fb92f999
commit
94eb269ade
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
8
.travis.yml
Normal file
8
.travis.yml
Normal file
@ -0,0 +1,8 @@
|
||||
language: csharp
|
||||
mono: none
|
||||
solution: CryptoExchange.Net.sln
|
||||
dotnet: 2.0.0
|
||||
dist: trusty
|
||||
script:
|
||||
- dotnet build CryptoExchange.Net/CryptoExchange.Net.csproj --framework "netstandard2.0"
|
||||
- dotnet test CryptoExchange.Net.UnitTests/CryptoExchange.Net.UnitTests.csproj
|
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<packagereference Include="Microsoft.NET.Test.Sdk" Version="15.0.0"></packagereference>
|
||||
<PackageReference Include="Moq" Version="4.7.145" />
|
||||
<packagereference Include="NUnit" Version="3.6.1"></packagereference>
|
||||
<packagereference Include="NUnit3TestAdapter" Version="3.8.0-alpha1"></packagereference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CryptoExchange.Net\CryptoExchange.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
223
CryptoExchange.Net.UnitTests/ExchangeClientTests.cs
Normal file
223
CryptoExchange.Net.UnitTests/ExchangeClientTests.cs
Normal file
@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CryptoExchange.Net.Authentication;
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Logging;
|
||||
using CryptoExchange.Net.RateLimiter;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace CryptoExchange.Net.UnitTests
|
||||
{
|
||||
[TestFixture()]
|
||||
public class ExchangeClientTests
|
||||
{
|
||||
[TestCase(null, null)]
|
||||
[TestCase("", "")]
|
||||
[TestCase("test", null)]
|
||||
[TestCase("test", "")]
|
||||
[TestCase(null, "test")]
|
||||
[TestCase("", "test")]
|
||||
public void SettingEmptyValuesForAPICredentials_Should_ThrowException(string key, string secret)
|
||||
{
|
||||
// arrange
|
||||
var client = PrepareClient("");
|
||||
|
||||
// act
|
||||
// assert
|
||||
Assert.Throws(typeof(ArgumentException), () => client.SetApiCredentails(key, secret));
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public void SettingLogOutput_Should_RedirectLogOutput()
|
||||
{
|
||||
// arrange
|
||||
var stringBuilder = new StringBuilder();
|
||||
var client = PrepareClient("{}", true, LogVerbosity.Debug, new StringWriter(stringBuilder));
|
||||
|
||||
// act
|
||||
client.TestCall();
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(string.IsNullOrEmpty(stringBuilder.ToString()));
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public void ObjectDeserializationFail_Should_GiveFailedResult()
|
||||
{
|
||||
// arrange
|
||||
var errorMessage = "TestErrorMessage";
|
||||
var client = PrepareClient(JsonConvert.SerializeObject(errorMessage));
|
||||
|
||||
// act
|
||||
var result = client.TestCall();
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreNotEqual(0, result.Error.Code);
|
||||
Assert.IsTrue(result.Error.Message.Contains(errorMessage));
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public void InvalidJson_Should_GiveFailedResult()
|
||||
{
|
||||
// arrange
|
||||
var errorMessage = "TestErrorMessage";
|
||||
var client = PrepareClient(JsonConvert.SerializeObject(errorMessage));
|
||||
|
||||
// act
|
||||
var result = client.TestCall();
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreNotEqual(0, result.Error.Code);
|
||||
Assert.IsTrue(result.Error.Message.Contains(errorMessage));
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public void WhenUsingRateLimiterTotalRequests_Should_BeDelayed()
|
||||
{
|
||||
// arrange
|
||||
var client = PrepareClient(JsonConvert.SerializeObject(new TestObject()));
|
||||
client.AddRateLimiter(new RateLimiterTotal(1, TimeSpan.FromSeconds(5)));
|
||||
|
||||
// act
|
||||
var sw = Stopwatch.StartNew();
|
||||
client.TestCall();
|
||||
client.TestCall();
|
||||
client.TestCall();
|
||||
sw.Stop();
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(sw.ElapsedMilliseconds > 9000);
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public void WhenUsingRateLimiterPerEndpointRequests_Should_BeDelayed()
|
||||
{
|
||||
// arrange
|
||||
var client = PrepareClient(JsonConvert.SerializeObject(new TestObject()));
|
||||
client.AddRateLimiter(new RateLimiterTotal(1, TimeSpan.FromSeconds(5)));
|
||||
|
||||
// act
|
||||
var sw = Stopwatch.StartNew();
|
||||
client.TestCall();
|
||||
client.TestCall();
|
||||
client.TestCall();
|
||||
sw.Stop();
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(sw.ElapsedMilliseconds > 9000);
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public void WhenRemovingRateLimiterRequest_Should_NoLongerBeDelayed()
|
||||
{
|
||||
// arrange
|
||||
var client = PrepareClient(JsonConvert.SerializeObject(new TestObject()));
|
||||
client.AddRateLimiter(new RateLimiterTotal(1, TimeSpan.FromSeconds(5)));
|
||||
client.RemoveRateLimiters();
|
||||
|
||||
// act
|
||||
var sw = Stopwatch.StartNew();
|
||||
client.TestCall();
|
||||
client.TestCall();
|
||||
client.TestCall();
|
||||
sw.Stop();
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(sw.ElapsedMilliseconds < 5000);
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public void ReceivingErrorStatusCode_Should_NotSuccess()
|
||||
{
|
||||
// arrange
|
||||
var client = PrepareExceptionClient(JsonConvert.SerializeObject(new TestObject()), "InvalidStatusCodeResponse", 203);
|
||||
|
||||
// act
|
||||
var result = client.TestCall();
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.IsNotNull(result.Error);
|
||||
Assert.IsTrue(result.Error.Message.Contains("InvalidStatusCodeResponse"));
|
||||
}
|
||||
|
||||
private TestImplementation PrepareClient(string responseData, bool withOptions = true, LogVerbosity verbosity = LogVerbosity.Warning, TextWriter tw = null)
|
||||
{
|
||||
var expectedBytes = Encoding.UTF8.GetBytes(responseData);
|
||||
var responseStream = new MemoryStream();
|
||||
responseStream.Write(expectedBytes, 0, expectedBytes.Length);
|
||||
responseStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var response = new Mock<IResponse>();
|
||||
response.Setup(c => c.GetResponseStream()).Returns(responseStream);
|
||||
|
||||
var request = new Mock<IRequest>();
|
||||
request.Setup(c => c.Headers).Returns(new WebHeaderCollection());
|
||||
request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
|
||||
request.Setup(c => c.GetResponse()).Returns(Task.FromResult(response.Object));
|
||||
|
||||
var factory = new Mock<IRequestFactory>();
|
||||
factory.Setup(c => c.Create(It.IsAny<string>()))
|
||||
.Returns(request.Object);
|
||||
TestImplementation client;
|
||||
if (withOptions)
|
||||
{
|
||||
client = new TestImplementation(new ExchangeOptions()
|
||||
{
|
||||
ApiCredentials = new ApiCredentials("Test", "Test2"),
|
||||
LogVerbosity = verbosity,
|
||||
LogWriter = tw
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
client = new TestImplementation();
|
||||
}
|
||||
client.RequestFactory = factory.Object;
|
||||
return client;
|
||||
}
|
||||
|
||||
private TestImplementation PrepareExceptionClient(string responseData, string exceptionMessage, int statusCode, bool credentials = true)
|
||||
{
|
||||
var expectedBytes = Encoding.UTF8.GetBytes(responseData);
|
||||
var responseStream = new MemoryStream();
|
||||
responseStream.Write(expectedBytes, 0, expectedBytes.Length);
|
||||
responseStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var we = new WebException();
|
||||
var r = new HttpWebResponse();
|
||||
var re = new HttpResponseMessage();
|
||||
|
||||
typeof(HttpResponseMessage).GetField("_statusCode", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(re, (HttpStatusCode)statusCode);
|
||||
typeof(HttpWebResponse).GetField("_httpResponseMessage", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(r, re);
|
||||
typeof(WebException).GetField("_message", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(we, exceptionMessage);
|
||||
typeof(WebException).GetField("_response", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(we, r);
|
||||
|
||||
var response = new Mock<IResponse>();
|
||||
response.Setup(c => c.GetResponseStream()).Throws(we);
|
||||
|
||||
var request = new Mock<IRequest>();
|
||||
request.Setup(c => c.Headers).Returns(new WebHeaderCollection());
|
||||
request.Setup(c => c.GetResponse()).Returns(Task.FromResult(response.Object));
|
||||
|
||||
var factory = new Mock<IRequestFactory>();
|
||||
factory.Setup(c => c.Create(It.IsAny<string>()))
|
||||
.Returns(request.Object);
|
||||
|
||||
TestImplementation client = credentials ? new TestImplementation(new ExchangeOptions() { ApiCredentials = new ApiCredentials("Test", "Test2") }) : new TestImplementation();
|
||||
client.RequestFactory = factory.Object;
|
||||
return client;
|
||||
}
|
||||
}
|
||||
}
|
55
CryptoExchange.Net.UnitTests/TestImplementation.cs
Normal file
55
CryptoExchange.Net.UnitTests/TestImplementation.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using CryptoExchange.Net.Authentication;
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
|
||||
namespace CryptoExchange.Net.UnitTests
|
||||
{
|
||||
public class TestImplementation: ExchangeClient
|
||||
{
|
||||
public TestImplementation(): base(new ExchangeOptions(), null) { }
|
||||
|
||||
public TestImplementation(ExchangeOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
|
||||
{
|
||||
}
|
||||
|
||||
public void SetApiCredentails(string key, string secret)
|
||||
{
|
||||
SetAuthenticationProvider(new TestAuthProvider(new ApiCredentials(key, secret)));
|
||||
}
|
||||
|
||||
public CallResult<TestObject> TestCall()
|
||||
{
|
||||
return ExecuteRequest<TestObject>(new Uri("http://www.test.com")).Result;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestAuthProvider : AuthenticationProvider
|
||||
{
|
||||
public TestAuthProvider(ApiCredentials credentials) : base(credentials)
|
||||
{
|
||||
}
|
||||
|
||||
public override string AddAuthenticationToUriString(string uri, bool signed)
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
public override IRequest AddAuthenticationToRequest(IRequest request, bool signed)
|
||||
{
|
||||
return request;
|
||||
}
|
||||
|
||||
public override string Sign(string toSign)
|
||||
{
|
||||
return toSign;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestObject
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public List<string> Data { get; set; }
|
||||
}
|
||||
}
|
31
CryptoExchange.Net.sln
Normal file
31
CryptoExchange.Net.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2008
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CryptoExchange.Net", "CryptoExchange.Net\CryptoExchange.Net.csproj", "{3762140C-7FF9-46E5-8EC3-BFB3FC7ADB9B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CryptoExchange.Net.UnitTests", "CryptoExchange.Net.UnitTests\CryptoExchange.Net.UnitTests.csproj", "{FBFE1651-D43D-4D67-89B7-6C4AE9BA4496}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3762140C-7FF9-46E5-8EC3-BFB3FC7ADB9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3762140C-7FF9-46E5-8EC3-BFB3FC7ADB9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3762140C-7FF9-46E5-8EC3-BFB3FC7ADB9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3762140C-7FF9-46E5-8EC3-BFB3FC7ADB9B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FBFE1651-D43D-4D67-89B7-6C4AE9BA4496}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FBFE1651-D43D-4D67-89B7-6C4AE9BA4496}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FBFE1651-D43D-4D67-89B7-6C4AE9BA4496}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FBFE1651-D43D-4D67-89B7-6C4AE9BA4496}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0D1B9CE9-E0B7-4B8B-88BF-6EA2CC8CA3D7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Loading…
x
Reference in New Issue
Block a user