Skip to content

Commit

Permalink
MT-00 Added 3 Unit Tests and CI workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
DCay committed Apr 14, 2024
1 parent fbb51e0 commit 433e18f
Show file tree
Hide file tree
Showing 22 changed files with 446 additions and 22 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: CI

on:
push:
pull_request:
branches: [ main ]
env:
DOTNET_VERSION: '8.0.x'
jobs:
ci:
name: ci-${{matrix.os}}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Test
run: dotnet test --no-restore --verbosity normal
2 changes: 1 addition & 1 deletion .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Docker Image CI
name: Docker Image CD

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion src/Data/MeTube.Data/Repository/BaseRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace MeTube.Data.Repository;

public class BaseRepository<TEntity> where TEntity : BaseEntity
public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : BaseEntity
{
protected readonly MeTubeDbContext _dbContext;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace MeTube.Data.Repository.Channels;

public class ChannelRepository : BaseRepository<Channel>
public class ChannelRepository : BaseRepository<Channel>, IChannelRepository
{
public ChannelRepository(MeTubeDbContext dbContext) : base(dbContext)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using MeTube.Data.Models.Channels;

namespace MeTube.Data.Repository.Channels;

public interface IChannelRepository : IBaseRepository<Channel>
{
}
14 changes: 14 additions & 0 deletions src/Data/MeTube.Data/Repository/IBaseRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace MeTube.Data.Repository;

public interface IBaseRepository<TEntity>
{
Task<TEntity> CreateAsync(TEntity entity);

IQueryable<TEntity> GetAll();

IQueryable<TEntity> GetAllAsNoTracking();

Task<TEntity> EditAsync(TEntity entity);

Task<TEntity> DeleteAsync(TEntity entity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using MeTube.Data.Models.Reactions;

namespace MeTube.Data.Repository.Reactions;

public interface IReactionTypeRepository : IBaseRepository<ReactionType>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using MeTube.Data.Models.Reactions;

namespace MeTube.Data.Repository.Reactions;

public interface IVideoReactionRepository : IBaseRepository<VideoReaction>
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace MeTube.Data.Repository.Reactions;

public class ReactionTypeRepository : BaseRepository<ReactionType>
public class ReactionTypeRepository : BaseRepository<ReactionType>, IReactionTypeRepository
{
public ReactionTypeRepository(MeTubeDbContext dbContext)
: base(dbContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace MeTube.Data.Repository.Reactions;

public class VideoReactionRepository : BaseRepository<VideoReaction>
public class VideoReactionRepository : BaseRepository<VideoReaction>, IVideoReactionRepository
{
public VideoReactionRepository(MeTubeDbContext dbContext)
: base(dbContext)
Expand Down
7 changes: 7 additions & 0 deletions src/Data/MeTube.Data/Repository/Videos/IVideoRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using MeTube.Data.Models.Videos;

namespace MeTube.Data.Repository.Videos;

public interface IVideoRepository : IBaseRepository<Video>
{
}
4 changes: 1 addition & 3 deletions src/Data/MeTube.Data/Repository/Videos/VideoRepository.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using MeTube.Data.Models.Playlists;
using MeTube.Data.Models.Videos;
using Microsoft.EntityFrameworkCore;

namespace MeTube.Data.Repository.Videos;

public class VideoRepository : MetadataBaseRepository<Video>
public class VideoRepository : MetadataBaseRepository<Video>, IVideoRepository
{
public VideoRepository(MeTubeDbContext dbContext)
: base(dbContext)
Expand Down
7 changes: 7 additions & 0 deletions src/MeTube.sln
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeTube.Web.Models", "Web\Me
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeTube.Service.Mappings", "Service\MeTube.Service.Mappings\MeTube.Service.Mappings.csproj", "{E7C74408-E954-4733-A7B5-9151A1F8ADB6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeTube.Service.Tests", "Service\MeTube.Service.Tests\MeTube.Service.Tests.csproj", "{885B44A5-04D4-4B46-9E6B-523EF48A9346}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -57,6 +59,10 @@ Global
{E7C74408-E954-4733-A7B5-9151A1F8ADB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E7C74408-E954-4733-A7B5-9151A1F8ADB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7C74408-E954-4733-A7B5-9151A1F8ADB6}.Release|Any CPU.Build.0 = Release|Any CPU
{885B44A5-04D4-4B46-9E6B-523EF48A9346}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{885B44A5-04D4-4B46-9E6B-523EF48A9346}.Debug|Any CPU.Build.0 = Debug|Any CPU
{885B44A5-04D4-4B46-9E6B-523EF48A9346}.Release|Any CPU.ActiveCfg = Release|Any CPU
{885B44A5-04D4-4B46-9E6B-523EF48A9346}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -69,6 +75,7 @@ Global
{04732F2E-F73E-43A3-8783-0F42E0E57388} = {313E313D-7DE2-4FFA-801E-4A3A6E7D876D}
{AAC0C0F6-1E2C-4017-825F-56457DC82E16} = {2A3AEA9D-8F77-4E2E-8E3D-DBE167E082EB}
{E7C74408-E954-4733-A7B5-9151A1F8ADB6} = {313E313D-7DE2-4FFA-801E-4A3A6E7D876D}
{885B44A5-04D4-4B46-9E6B-523EF48A9346} = {313E313D-7DE2-4FFA-801E-4A3A6E7D876D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A7605E11-F2EC-4116-B2D1-323DAAA88E62}
Expand Down
33 changes: 33 additions & 0 deletions src/Service/MeTube.Service.Tests/MeTube.Service.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Data\MeTube.Data.Models\MeTube.Data.Models.csproj" />
<ProjectReference Include="..\..\Data\MeTube.Data\MeTube.Data.csproj" />
<ProjectReference Include="..\MeTube.Service.Mappings\MeTube.Service.Mappings.csproj" />
<ProjectReference Include="..\MeTube.Service.Models\MeTube.Service.Models.csproj" />
<ProjectReference Include="..\MeTube.Service\MeTube.Service.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>

</Project>
29 changes: 29 additions & 0 deletions src/Service/MeTube.Service.Tests/Mocks/TaskAsyncEnumerable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Linq.Expressions;

namespace MeTube.Service.Tests.Mocks;

public class TestAsyncEnumerable<T> : EnumerableQuery<T>, IAsyncEnumerable<T>, IQueryable<T>
{
public TestAsyncEnumerable(IEnumerable<T> enumerable)
: base(enumerable)
{ }

public TestAsyncEnumerable(Expression expression)
: base(expression)
{ }

public IAsyncEnumerator<T> GetEnumerator()
{
return new TestAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}

public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new TestAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}

IQueryProvider IQueryable.Provider
{
get { return new TestAsyncQueryProvider<T>(this); }
}
}
40 changes: 40 additions & 0 deletions src/Service/MeTube.Service.Tests/Mocks/TestAsyncEnumerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace MeTube.Service.Tests.Mocks;

public class TestAsyncEnumerator<T> : IAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;

public TestAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}

public void Dispose()
{
_inner.Dispose();
}

public T Current
{
get
{
return _inner.Current;
}
}

public Task<bool> MoveNext(CancellationToken cancellationToken)
{
return Task.FromResult(_inner.MoveNext());
}

public ValueTask<bool> MoveNextAsync()
{
return ValueTask.FromResult(_inner.MoveNext());
}

public ValueTask DisposeAsync()
{
_inner.Dispose();
return ValueTask.CompletedTask;
}
}
49 changes: 49 additions & 0 deletions src/Service/MeTube.Service.Tests/Mocks/TestAsyncQueryProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Microsoft.EntityFrameworkCore.Query;
using System.Linq.Expressions;

namespace MeTube.Service.Tests.Mocks;

public class TestAsyncQueryProvider<TEntity> : IAsyncQueryProvider
{
private readonly IQueryProvider _inner;

internal TestAsyncQueryProvider(IQueryProvider inner)
{
_inner = inner;
}

public IQueryable CreateQuery(Expression expression)
{
return new TestAsyncEnumerable<TEntity>(expression);
}

public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestAsyncEnumerable<TElement>(expression);
}

public object Execute(Expression expression)
{
return _inner.Execute(expression);
}

public TResult Execute<TResult>(Expression expression)
{
return _inner.Execute<TResult>(expression);
}

public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression expression)
{
return new TestAsyncEnumerable<TResult>(expression);
}

public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute<TResult>(expression));
}

TResult IAsyncQueryProvider.ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return (TResult)(object)Task.FromResult(Execute<TEntity>(expression));
}
}
55 changes: 55 additions & 0 deletions src/Service/MeTube.Service.Tests/Utilities/MoqExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using MeTube.Service.Tests.Mocks;
using Moq;

namespace MeTube.Service.Tests.Utilities;

public static class MoqExtensions
{
public static Mock<IQueryable<TEntity>> MockQueryable<TEntity>(IQueryable<TEntity> mockCollection)
{
var mockQueryable = new Mock<IQueryable<TEntity>>();

mockQueryable.As<IAsyncEnumerable<TEntity>>()
.Setup(m => m.GetAsyncEnumerator(It.IsAny<CancellationToken>()))
.Returns(new TestAsyncEnumerator<TEntity>(mockCollection.GetEnumerator()));

mockQueryable.As<IQueryable<TEntity>>()
.Setup(m => m.Provider)
.Returns(new TestAsyncQueryProvider<TEntity>(mockCollection.Provider));

mockQueryable.As<IQueryable<TEntity>>().Setup(m => m.Expression).Returns(mockCollection.Expression);
mockQueryable.As<IQueryable<TEntity>>().Setup(m => m.ElementType).Returns(mockCollection.ElementType);
mockQueryable.As<IQueryable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(() => mockCollection.GetEnumerator());

return mockQueryable;
}

public static bool CompareCollections<TEntity>(
IEnumerable<TEntity> firstCollection,
IEnumerable<TEntity> secondCollection,
Func<TEntity, TEntity, bool> comparer)
{
if (firstCollection.Count() != secondCollection.Count()) return false;

foreach (var expectedItem in firstCollection)
{
bool isPresent = false;

foreach (var actualItem in secondCollection)
{
if(comparer.Invoke(actualItem, expectedItem))
{
isPresent = true;
break;
}
}

if (!isPresent)
{
return false;
}
}

return true;
}
}
Loading

0 comments on commit 433e18f

Please sign in to comment.