Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.0 Mock Unit Testing #279

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Discord.Net.sln
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "src\Discord.Net\Discord.Net.xproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Tests", "test\Discord.Net.Tests\Discord.Net.Tests.xproj", "{69EECB8D-8705-424F-9202-F7F4051EE403}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,6 +23,10 @@ Global
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.Build.0 = Release|Any CPU
{69EECB8D-8705-424F-9202-F7F4051EE403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69EECB8D-8705-424F-9202-F7F4051EE403}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69EECB8D-8705-424F-9202-F7F4051EE403}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69EECB8D-8705-424F-9202-F7F4051EE403}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
97 changes: 0 additions & 97 deletions test/Discord.Net.Tests/Discord.Net.Tests.csproj

This file was deleted.

21 changes: 21 additions & 0 deletions test/Discord.Net.Tests/Discord.Net.Tests.xproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>69eecb8d-8705-424f-9202-f7f4051ee403</ProjectGuid>
<RootNamespace>Discord.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
45 changes: 45 additions & 0 deletions test/Discord.Net.Tests/Framework/MockRestClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Discord.Net.Rest;
using System.Collections.ObjectModel;

namespace Discord.Tests.Framework
{
public class MockRestClient : IRestClient
{
public MockRestClient(string baseUrl)
{
_requestHandler = new RequestHandler();
}

private Dictionary<string, string> _headers = new Dictionary<string, string>();
public IReadOnlyDictionary<string, string> Headers =>
new ReadOnlyDictionary<string, string>(_headers);
private RequestHandler _requestHandler;

public Task<Stream> SendAsync(string method, string endpoint, bool headerOnly = false) =>
SendAsync(method, endpoint, "", headerOnly);

public Task<Stream> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, bool headerOnly = false)
{
throw new NotImplementedException();
}

public Task<Stream> SendAsync(string method, string endpoint, string json, bool headerOnly = false)
{
return Task.FromResult(_requestHandler.GetMock(method, endpoint, json, Headers));
}

public void SetCancelToken(CancellationToken cancelToken) { }

public void SetHeader(string key, string value)
{
if (_headers.ContainsKey(key))
_headers.Remove(key);
_headers.Add(key, value);
}
}
}
23 changes: 23 additions & 0 deletions test/Discord.Net.Tests/Framework/Mocks/Rest/Guilds.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Discord.API;

namespace Discord.Tests.Framework.Mocks.Rest
{
public static class Guilds
{
public static Guild DiscordApi => new Guild()
{
Id = 81384788765712384,
Name = "Discord API",
OwnerId = 53905483156684800,
MfaLevel = 0,
VerificationLevel = 0,
Roles = new Role[] { Roles.Everyone(81384788765712384), Roles.DiscordEmployee, Roles.LibraryDevs },
AFKTimeout = 3600,
Region = "us-east",
DefaultMessageNotifications = (DefaultMessageNotifications)1,
EmbedChannelId = 81384788765712384,
EmbedEnabled = true,
Icon = "2aab26934e72b4ec300c5aa6cf67c7b3"
};
}
}
43 changes: 43 additions & 0 deletions test/Discord.Net.Tests/Framework/Mocks/Rest/Roles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Discord.API;

namespace Discord.Tests.Framework.Mocks.Rest
{
public static class Roles
{
// TODO: These mocks need to include 'mentionable' when the library implements it.

public static Role Everyone(ulong guildId) => new Role()
{
Id = guildId,
Name = "@everyone",
Color = 0,
Hoist = false,
Permissions = 104324097,
Position = 0,
Managed = false
};

public static Role LibraryDevs => new Role()
{
Id = 81793792671232000,
Name = "Library Devs",
Color = 42607,
Hoist = true,
Permissions = 268435456,
Position = 17,
Managed = false
};

public static Role DiscordEmployee => new Role()
{
Id = 103548914652696576,
Name = "Discord Employee",
Color = 10181046,
Hoist = false,
Permissions = 29368358,
Position = 20,
Managed = false
};

}
}
38 changes: 38 additions & 0 deletions test/Discord.Net.Tests/Framework/Mocks/Rest/Users.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Discord.API;

namespace Discord.Tests.Framework.Mocks.Rest
{
public static class Users
{
public static User SelfUser => new User()
{
Id = 103559217914318848,
Username = "Jake",
Discriminator = "0001",
Email = "[email protected]",
MfaEnabled = true,
Verified = true,
Avatar = "cdd7ae679ef37ce03e097221c70aeed6"
};

public static User BotSelfUser => new User()
{
Id = 145584102551060480,
Username = "foxboat",
Discriminator = "8888",
Email = null,
MfaEnabled = true,
Verified = true,
Avatar = "5f0be46cea584d2225e6c15e8418fb52",
Bot = true
};

public static User PublicUser => new User()
{
Id = 66078337084162048,
Username = "foxbot",
Discriminator = "0282",
Avatar = "cdd7ae679ef37ce03e097221c70aeed6"
};
}
}
47 changes: 47 additions & 0 deletions test/Discord.Net.Tests/Framework/RequestHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Net;
using System.Text;
using UserRoutes = Discord.Tests.Framework.Routes.Users;
using GuildRoutes = Discord.Tests.Framework.Routes.Guilds;
using Contracts = Discord.Tests.Framework.Routes.Contracts;
using Newtonsoft.Json;
using Discord.Net.Converters;
using Discord.Net;

namespace Discord.Tests.Framework
{
public class RequestHandler
{
public delegate object Response(string json, IReadOnlyDictionary<string, string> requestHeaders);

internal static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { ContractResolver = new DiscordContractResolver() };

internal Dictionary<string, Response> Routes = new Dictionary<string, Response>()
{
// --- USERS
// Get Current User
["GET users/@me"] = new Response(UserRoutes.Me),
// Get User by ID
["GET users/66078337084162048"] = new Response(UserRoutes.Public),
// Get User by Tag
["GET users?q=foxbot%230282&limit=1"] = new Response(UserRoutes.Query),
// --- GUILDS
["GET guilds/81384788765712384"] = new Response(GuildRoutes.DiscordApi)
};

internal Stream GetMock(string method, string endpoint, string json, IReadOnlyDictionary<string, string> requestHeaders)
{
var key = string.Format("{0} {1}", method.ToUpperInvariant(), endpoint.ToLowerInvariant());
if (!Routes.ContainsKey(key))
throw new HttpException(HttpStatusCode.NotFound, $"{key}: {json}");
Contracts.EnsureAuthorization(requestHeaders);
var model = Routes[key].Invoke(json, requestHeaders);
var textResponse = JsonConvert.SerializeObject(model, SerializerSettings);
return new MemoryStream(Encoding.UTF8.GetBytes(textResponse));
}
}
}
24 changes: 24 additions & 0 deletions test/Discord.Net.Tests/Framework/Routes/Contracts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Discord.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace Discord.Tests.Framework.Routes
{
public static class Contracts
{
public static readonly string UserToken = "token.user";
public static readonly string BotToken = "token.bot";
public static readonly string BearerToken = "token.bearer";

public static void EnsureAuthorization(IReadOnlyDictionary<string, string> requestHeaders)
{
if (!requestHeaders.ContainsKey("authorization")) throw new HttpException(HttpStatusCode.Forbidden);
if (requestHeaders["authorization"] != UserToken
&& requestHeaders["authorization"] != $"Bot {BotToken}"
&& requestHeaders["authorization"] != $"Bearer {BearerToken}") throw new HttpException(HttpStatusCode.Forbidden);
}
}
}
11 changes: 11 additions & 0 deletions test/Discord.Net.Tests/Framework/Routes/Guilds.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;
using GuildMocks = Discord.Tests.Framework.Mocks.Rest.Guilds;

namespace Discord.Tests.Framework.Routes
{
public static class Guilds
{
public static object DiscordApi(string json, IReadOnlyDictionary<string, string> requestHeaders) =>
GuildMocks.DiscordApi;
}
}
Loading