Skip to content

Commit

Permalink
DEVX-6546 | [Video] Refactoring (#316)
Browse files Browse the repository at this point in the history
* Remove duplication when creating WireMock requests/responses

* Implement UseCaseHelper to reduce duplication

* Code cleanup

* Reduce duplication on property-based tests

* Use generator for FsCheck, use HttpStatusCode instead of string for ErrorResponse

* Create method for converting an ErrorReponse to HttpFailure

* Implement ValueObject and StringIdentifier

* Implement implicit operator for Identifier

* Missing constant on Identifier

* Address duplication in InputValidation
  • Loading branch information
Tr00d authored Dec 22, 2022
1 parent 071eeca commit 30201ad
Show file tree
Hide file tree
Showing 48 changed files with 646 additions and 480 deletions.
16 changes: 9 additions & 7 deletions Vonage.Video.Beta.Test/Common/JsonSerializerTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FluentAssertions;
using System.Net;
using FluentAssertions;
using Vonage.Video.Beta.Common;
using Vonage.Video.Beta.Test.Extensions;
using Xunit;
Expand All @@ -7,14 +8,14 @@ namespace Vonage.Video.Beta.Test.Common
{
public class JsonSerializerTest
{
private const string DummyString = @"{""id"":10,""name"":""Hello World""}";
private const string DummyString = @"{""id"":10,""name"":""Hello World"",""code"":200}";
private readonly JsonSerializer serializer;

public JsonSerializerTest() => this.serializer = new JsonSerializer();

[Fact]
public void SerializeObject_ShouldReturnSerializedString() => this.serializer
.SerializeObject(new DummyObject {Id = 10, Name = "Hello World"}).Should()
.SerializeObject(new DummyObject {Id = 10, Name = "Hello World", Code = HttpStatusCode.OK}).Should()
.Be(DummyString);

[Theory]
Expand All @@ -28,19 +29,20 @@ public void DeserializeObject_ShouldReturnFailure_GivenDeserializationFailed(str
failure.GetFailureMessage().Should().Be($"Unable to deserialize '{value}' into 'DummyObject'."));

[Theory]
[InlineData("{}", 0, null)]
[InlineData(DummyString, 10, "Hello World")]
[InlineData("{}", 0, null, new HttpStatusCode())]
[InlineData(DummyString, 10, "Hello World", HttpStatusCode.OK)]
public void DeserializeObject_ShouldReturnSuccess_GivenDeserializationSucceeded(string value, int expectedId,
string expectedName) =>
string expectedName, HttpStatusCode expectedCode) =>
this.serializer
.DeserializeObject<DummyObject>(value)
.Should()
.BeSuccess(new DummyObject {Id = expectedId, Name = expectedName});
.BeSuccess(new DummyObject {Id = expectedId, Name = expectedName, Code = expectedCode});

private struct DummyObject
{
public int Id { get; set; }
public string Name { get; set; }
public HttpStatusCode Code { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using System;
using FluentAssertions;
using Vonage.Video.Beta.Common;
using Vonage.Video.Beta.Common.Monads;
using Vonage.Video.Beta.Test.Extensions;
using Xunit;

namespace Vonage.Video.Beta.Test.Common
namespace Vonage.Video.Beta.Test.Common.Monads
{
public class MaybeTest
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System;
using System.Threading.Tasks;
using FluentAssertions;
using Vonage.Video.Beta.Common;
using Vonage.Video.Beta.Common.Failures;
using Vonage.Video.Beta.Common.Monads;
using Vonage.Video.Beta.Test.Extensions;
using Xunit;

namespace Vonage.Video.Beta.Test.Common
namespace Vonage.Video.Beta.Test.Common.Monads
{
public class ResultTest
{
Expand Down
59 changes: 59 additions & 0 deletions Vonage.Video.Beta.Test/Common/ValueObjectTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System.Collections.Generic;
using FluentAssertions;
using Vonage.Video.Beta.Common;
using Xunit;

namespace Vonage.Video.Beta.Test.Common
{
public class ValueObjectTest
{
[Fact]
public void Equals_ShouldReturnFalse_GivenValueAreDifferent() =>
FakeValueObject.Hello.Equals(FakeValueObject.World).Should().BeFalse();

[Fact]
public void Equals_ShouldReturnTrue_GivenValueAreSame() =>
FakeValueObject.Hello.Equals(FakeValueObject.Hello).Should().BeTrue();

[Fact]
public void EqualsOperator_ShouldReturnFalse_GivenValueAreDifferent() =>
(FakeValueObject.Hello == FakeValueObject.World).Should().BeFalse();

[Fact]
public void EqualsOperator_ShouldReturnTrue_GivenValueAreSame() =>
(FakeValueObject.Hello == FakeValueObject.Hello).Should().BeTrue();

[Fact]
public void DifferentOperator_ShouldReturnFalse_GivenValueAreSame() =>
(FakeValueObject.Hello != FakeValueObject.Hello).Should().BeFalse();

[Fact]
public void DifferentOperator_ShouldReturnTrue_GivenValueAreDifferent() =>
(FakeValueObject.Hello != FakeValueObject.World).Should().BeTrue();

[Fact]
public void GetHashCode_ShouldReturnSameValue_GivenValueAreSame() =>
FakeValueObject.Hello.GetHashCode().Should()
.Be(FakeValueObject.Hello.GetHashCode());

[Fact]
public void GetHashCode_ShouldReturnDifferent_GivenValueAreDifferent() =>
FakeValueObject.Hello.GetHashCode().Should()
.NotBe(FakeValueObject.World.GetHashCode());

private class FakeValueObject : ValueObject<string>
{
private readonly string value;

private FakeValueObject(string value)
{
this.value = value;
}

public static FakeValueObject Hello => new FakeValueObject("Hello");
public static FakeValueObject World => new FakeValueObject("World");

protected override IEnumerable<object> GetEqualityComponents() => new[] {this.value};
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Vonage.Video.Beta.Common;
using Vonage.Video.Beta.Common.Monads;

namespace Vonage.Video.Beta.Test.Extensions
{
Expand Down
33 changes: 32 additions & 1 deletion Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
using System.Net;
using FsCheck;
using Vonage.Video.Beta.Video.Sessions;

namespace Vonage.Video.Beta.Test.Extensions
{
/// <summary>
/// Extensions for FsCheck.
/// </summary>
public static class FsCheckExtensions
{
public static Arbitrary<HttpStatusCode> GetInvalidStatusCodes() => Arb.From<HttpStatusCode>()
/// <summary>
/// Retrieves a HttpStatusCode generator that produces only invalid codes.
/// </summary>
/// <returns>An Arbitrary of status codes.</returns>
public static Arbitrary<HttpStatusCode> GetInvalidStatusCodes() => GetAny<HttpStatusCode>()
.MapFilter(_ => _, code => (int) code >= 400 && (int) code < 600);

/// <summary>
/// Retrieves a string generator that produces only non-null/non-empty string.
/// </summary>
/// <returns>An Arbitrary of strings.</returns>
public static Arbitrary<string> GetNonEmptyStrings() =>
GetAny<string>().MapFilter(_ => _, value => !string.IsNullOrWhiteSpace(value));

/// <summary>
/// Retrieves a generator that produces any value.
/// </summary>
/// <typeparam name="T">Type of the value.</typeparam>
/// <returns>An Arbitrary.</returns>
public static Arbitrary<T> GetAny<T>() => Arb.From<T>();

/// <summary>
/// Retrieves a generator that produces error responses with invalid status codes.
/// </summary>
/// <returns>An Arbitrary of ErrorResponse.</returns>
public static Arbitrary<ErrorResponse> GetErrorResponses() =>
Arb.From(from message in GetAny<string>().Generator
from code in GetInvalidStatusCodes().Generator
select new ErrorResponse(code, message));
}
}
6 changes: 3 additions & 3 deletions Vonage.Video.Beta.Test/Extensions/MaybeAssertionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using FluentAssertions;
using FluentAssertions.Execution;
using FluentAssertions.Primitives;
using Vonage.Video.Beta.Common;
using Vonage.Video.Beta.Common.Monads;

namespace Vonage.Video.Beta.Test.Extensions
{
Expand All @@ -12,8 +12,6 @@ public MaybeAssertionExtensions(Maybe<T> subject) : base(subject)
{
}

protected override string Identifier => "maybe";

public AndConstraint<MaybeAssertionExtensions<T>> BeNone(string because = "", params object[] becauseArgs)
{
Execute.Assertion
Expand Down Expand Up @@ -52,5 +50,7 @@ public AndConstraint<MaybeAssertionExtensions<T>> BeSome(T expected, string beca
.FailWith("but found Some {0}.", this.Subject);
return new AndConstraint<MaybeAssertionExtensions<T>>(this);
}

protected override string Identifier => "maybe";
}
}
7 changes: 4 additions & 3 deletions Vonage.Video.Beta.Test/Extensions/ResultAssertionExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
using FluentAssertions;
using FluentAssertions.Execution;
using FluentAssertions.Primitives;
using Vonage.Video.Beta.Common;
using Vonage.Video.Beta.Common.Failures;
using Vonage.Video.Beta.Common.Monads;

namespace Vonage.Video.Beta.Test.Extensions
{
Expand All @@ -12,8 +13,6 @@ public ResultAssertionExtension(Result<T> subject) : base(subject)
{
}

protected override string Identifier => "result";

public AndConstraint<ResultAssertionExtension<T>> BeFailure(Action<IResultFailure> action, string because = "",
params object[] becauseArgs)
{
Expand Down Expand Up @@ -69,5 +68,7 @@ public AndConstraint<ResultAssertionExtension<T>> BeFailure(IResultFailure expec
.FailWith("but found Success {0}.", this.Subject);
return new AndConstraint<ResultAssertionExtension<T>>(this);
}

protected override string Identifier => "result";
}
}
50 changes: 44 additions & 6 deletions Vonage.Video.Beta.Test/Extensions/WireMockExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,53 @@
using WireMock.RequestBuilders;
using System.Net;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;

namespace Vonage.Video.Beta.Test.Extensions
{
/// <summary>
/// Extensions for WireMock.Net
/// </summary>
public static class WireMockExtensions
{
public static IRequestBuilder BuildRequestWithAuthenticationHeader(string token) =>
/// <summary>
/// Creates a response.
/// </summary>
/// <param name="code">The http status code</param>
/// <param name="body">The response body.</param>
/// <returns>The response.</returns>
public static IResponseBuilder CreateResponse(HttpStatusCode code, string body) =>
body is null ? CreateResponse(code) : CreateResponse(code).WithBody(body);

/// <summary>
/// Creates a response without a body.
/// </summary>
/// <param name="code">The http status code</param>
/// <returns>The response.</returns>
public static IResponseBuilder CreateResponse(HttpStatusCode code) =>
Response.Create().WithStatusCode(code);

/// <summary>
/// Creates a request.
/// </summary>
/// <param name="token">The authentication token.</param>
/// <param name="path">The endpoint path.</param>
/// <param name="body">The body.</param>
/// <returns>The request.</returns>
public static IRequestBuilder CreateRequest(string token, string path, string body) =>
body is null ? CreateRequest(token, path) : CreateRequest(token, path).WithBody(body);

/// <summary>
/// Creates a request without a body.
/// </summary>
/// <param name="token">The authentication token.</param>
/// <param name="path">The endpoint path.</param>
/// <returns>The request.</returns>
public static IRequestBuilder CreateRequest(string token, string path) =>
BuildRequestWithAuthenticationHeader(token).WithPath(path);

private static IRequestBuilder BuildRequestWithAuthenticationHeader(string token) =>
WireMock.RequestBuilders.Request
.Create()
.WithAuthenticationHeader(token);

public static IRequestBuilder WithAuthenticationHeader(this IRequestBuilder builder, string token) =>
builder.WithHeader("Authorization", $"Bearer {token}");
.WithHeader("Authorization", $"Bearer {token}");
}
}
Loading

0 comments on commit 30201ad

Please sign in to comment.