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

MT-00 Unit Testing and CI configured #17

Merged
merged 5 commits into from
Apr 14, 2024
Merged
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
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]
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 ./src
- name: Build
run: dotnet build ./src --configuration Release --no-restore
- name: Test
run: dotnet test ./src --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
Loading