Skip to content
This repository has been archived by the owner on Oct 14, 2022. It is now read-only.

test: Unit Tests for Companies #18

Merged
merged 1 commit into from
Jun 11, 2022
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
62 changes: 62 additions & 0 deletions WAW.API.Tests/Features/Company.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
Feature: Companies API
As a developer
I want to manage Companies through an API
In order to make it available for client applications.

Scenario: Get all Companies
Given I am a Companies client
And the Companies repository has data
| Id | Name | Address | Email |
| 1 | Google Inc. | Lima, PE | google@fake.com |
| 2 | Meta Inc. | Santiago, CH | meta@fake.com |
When a GET request is sent to Companies
Then a CompanyResource response with status 200 is received
And a list of CompanyResources is included in the body
| Id | Name | Address | Email |
| 1 | Google Inc. | Lima, PE | google@fake.com |
| 2 | Meta Inc. | Santiago, CH | meta@fake.com |

Scenario: Add Company with data
Given I am a Companies client
And the Companies repository has data
| Id | Name | Address | Email |
| 1 | Google Inc. | Lima, PE | google@fake.com |
| 2 | Meta Inc. | Santiago, CH | meta@fake.com |
When a POST request is sent to Companies
| Name | Address | Email |
| Oracle | Buenos Aires, AR | oracle@fake.com |
Then a CompanyResource response with status 200 is received
And a CompanyResource is included in the body
| Id | Name | Address | Email |
| 3 | Oracle | Buenos Aires, AR | oracle@fake.com |

Scenario: Add invalid Company
Given I am a Companies client
When a POST request is sent to Companies
| Name | Address | Email |
| | Quito, EC | company@fake.com |
Then a CompanyResource response with status 400 is received
And a CompanyResource Error Message is included in the body
| Message |
| The Name field is required. |

Scenario: Update existing Company
Given I am a Companies client
And the Companies repository has data
| Id | Name | Address | Email |
| 1 | Google Inc. | Lima, PE | google@fake.com |
When a PUT request is sent to Companies with Id 1
| Name | Address | Email |
| Google Inc. | Huacho, PE | newgoogle@fake.com |
Then a CompanyResource response with status 200 is received
And a CompanyResource is included in the body
| Id | Name | Address | Email |
| 1 | Google Inc. | Huacho, PE | newgoogle@fake.com |

Scenario: Delete existing Company
Given I am a Companies client
And the Companies repository has data
| Id | Name | Address | Email |
| 1 | Google Inc. | Lima, PE | google@fake.com |
When a DELETE request is sent to Companies with Id 1
Then a CompanyResource response with status 200 is received
43 changes: 43 additions & 0 deletions WAW.API.Tests/Helpers/AppFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using WAW.API.Shared.Persistence.Contexts;

namespace WAW.API.Tests.Helpers;

public static class AppFactory {
public static WebApplicationFactory<Program> GetWebApplicationFactory() {
return new WebApplicationFactory<Program>().WithWebHostBuilder(
builder => {
builder.ConfigureTestServices(
services => {
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<AppDbContext>));
if (descriptor is not null) {
services.Remove(descriptor);
}

services.AddDbContext<AppDbContext>(
options => options.UseInMemoryDatabase("InMemoryTestDatabase")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
);

var provider = services.BuildServiceProvider();
var scope = provider.CreateScope();
var scopedServices = scope.ServiceProvider;
var ctx = scopedServices.GetRequiredService<AppDbContext>();

ctx.Database.EnsureDeleted();
ctx.Database.EnsureCreated();
}
);

builder.UseEnvironment("Testing");
}
);
}
}
5 changes: 5 additions & 0 deletions WAW.API.Tests/Helpers/TextError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace WAW.API.Tests.Helpers;

public class TextError {
public string Message { get; set; } = string.Empty;
}
38 changes: 38 additions & 0 deletions WAW.API.Tests/Hooks/CompanyHooks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using BoDi;
using Microsoft.AspNetCore.Mvc.Testing;
using WAW.API.Employers.Domain.Repositories;
using WAW.API.Shared.Domain.Repositories;
using WAW.API.Tests.Helpers;

namespace WAW.API.Tests.Hooks;

[Binding]
public class CompanyHooks {
private readonly IObjectContainer objectContainer;

public CompanyHooks(IObjectContainer objectContainer) {
this.objectContainer = objectContainer;
}

[BeforeScenario]
public async Task RegisterServices() {
var factory = AppFactory.GetWebApplicationFactory();
await ClearData(factory);
objectContainer.RegisterInstanceAs(factory);
var companiesRepository = factory.Services.GetService(typeof(ICompanyRepository)) as ICompanyRepository;
objectContainer.RegisterInstanceAs(companiesRepository);
var unitOfWork = factory.Services.GetService(typeof(IUnitOfWork)) as IUnitOfWork;
objectContainer.RegisterInstanceAs(unitOfWork);
}

private static async Task ClearData(WebApplicationFactory<Program> factory) {
if (factory.Services.GetService(typeof(ICompanyRepository)) is not ICompanyRepository companyRepository) {
return;
}

var entities = await companyRepository.ListAll();
foreach (var entity in entities) {
companyRepository.Remove(entity);
}
}
}
12 changes: 12 additions & 0 deletions WAW.API.Tests/Hooks/SharedHooks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Globalization;
using TechTalk.SpecFlow.Assist.ValueRetrievers;

namespace WAW.API.Tests.Hooks;

[Binding]
public sealed class SharedHooks {
[BeforeTestRun]
public static void BeforeTestRun() {
DateTimeValueRetriever.DateTimeStyles = DateTimeStyles.AssumeUniversal;
}
}
102 changes: 102 additions & 0 deletions WAW.API.Tests/Steps/CompanySteps.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System.Net;
using System.Net.Http.Json;
using System.Net.Mime;
using System.Text;
using Microsoft.AspNetCore.Mvc.Testing;
using Newtonsoft.Json;
using TechTalk.SpecFlow.Assist;
using WAW.API.Employers.Domain.Models;
using WAW.API.Employers.Domain.Repositories;
using WAW.API.Employers.Resources;
using WAW.API.Shared.Domain.Repositories;
using WAW.API.Tests.Helpers;
using Xunit;

namespace WAW.API.Tests.Steps;

[Binding]
public class CompanySteps {
private const string endpoint = "/api/v1/companies";
private readonly WebApplicationFactory<Program> factory;
private readonly ICompanyRepository repository;
private readonly IUnitOfWork unitOfWork;
private HttpClient client = null!;
private HttpResponseMessage response = null!;
private CompanyResource? entity;
private IEnumerable<CompanyResource>? entities;

public CompanySteps(
WebApplicationFactory<Program> factory,
ICompanyRepository repository,
IUnitOfWork unitOfWork
) {
this.factory = factory;
this.repository = repository;
this.unitOfWork = unitOfWork;
}

[Given(@"I am a Companies client")]
public void GivenIAmACompaniesClient() {
client = factory.CreateDefaultClient();
}

[Given(@"the Companies repository has data")]
public async Task GivenTheCompaniesRepositoryHasData(Table table) {
var entries = table.CreateSet<Company>();
foreach (var entry in entries) {
await repository.Add(entry);
await unitOfWork.Complete();
}
}

[When(@"a GET request is sent to Companies")]
public async Task WhenAGetRequestIsSentToCompanies() {
response = await client.GetAsync(endpoint);
}

[When(@"a POST request is sent to Companies")]
public async Task WhenAPostRequestIsSentToCompanies(Table table) {
var data = table.CreateInstance<CompanyRequest>();
var json = JsonConvert.SerializeObject(data);
var content = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json);
response = await client.PostAsync(endpoint, content);
}

[When(@"a PUT request is sent to Companies with Id (.*)")]
public async Task WhenAPutRequestIsSentToCompaniesWithId(int id, Table table) {
var data = table.CreateInstance<CompanyRequest>();
var json = JsonConvert.SerializeObject(data);
var content = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json);
response = await client.PutAsync($"{endpoint}/{id}", content);
}

[When(@"a DELETE request is sent to Companies with Id (.*)")]
public async Task WhenADeleteRequestIsSentToCompaniesWithId(int id) {
response = await client.DeleteAsync($"{endpoint}/{id}");
}

[Then(@"a CompanyResource response with status (.*) is received")]
public void ThenACompanyResourceResponseWithStatusIsReceived(int status) {
var expected = (HttpStatusCode) status;
Assert.Equal(expected, response.StatusCode);
}

[Then(@"a list of CompanyResources is included in the body")]
public async Task ThenAListOfCompanyResourcesIsIncludedInTheBody(Table table) {
entities = await response.Content.ReadFromJsonAsync<List<CompanyResource>>();
table.CompareToSet(entities);
}

[Then(@"a CompanyResource is included in the body")]
public async Task ThenACompanyResourceIsIncludedInTheBody(Table table) {
entity = await response.Content.ReadFromJsonAsync<CompanyResource>();
table.CompareToInstance(entity);
}

[Then(@"a CompanyResource Error Message is included in the body")]
public async Task ThenACompanyResourceErrorMessageIsIncludedInTheBody(Table table) {
var text = await response.Content.ReadAsStringAsync();
var error = table.CreateInstance<TextError>();
Assert.Contains(error.Message, text);
}
}
6 changes: 0 additions & 6 deletions WAW.API.Tests/WAW.API.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,4 @@
<ProjectReference Include="..\WAW.API\WAW.API.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Features" />
<Folder Include="Hooks" />
<Folder Include="Steps" />
</ItemGroup>

</Project>