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

Add WithDependency<T, T2>(T2, Action<T2>) overload #4

Merged
merged 1 commit into from
Oct 13, 2020
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
7 changes: 3 additions & 4 deletions FluentArrange.NSubstitute/FluentArrange.NSubstitute.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<Version>0.2.0-alpha</Version>
<Version>0.3.0-alpha</Version>
<Description>FluentArrange using NSubstitute as mocking framework.</Description>
<PackageProjectUrl>https://github.com/hhoangnl/FluentArrange</PackageProjectUrl>
<RepositoryUrl>https://github.com/hhoangnl/FluentArrange</RepositoryUrl>
<PackageReleaseNotes>Added overloads to accept instances:
- WithDependency&lt;T&gt;(T)
- WithDependency&lt;T&gt;(T, Action&lt;T&gt;)</PackageReleaseNotes>
<PackageReleaseNotes>Added overload to configure and call T2-specific methods:
- WithDependency&lt;T, T2&gt;(T2, Action&lt;T2&gt;)</PackageReleaseNotes>
<PackageTags>AAA TDD mocking unit-testing nsubstitute</PackageTags>
<Authors>Huy Hoang</Authors>
<Copyright>Huy Hoang</Copyright>
Expand Down
88 changes: 64 additions & 24 deletions FluentArrange.Tests/FluentArrangeContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,39 @@ namespace FluentArrange.Tests
public class FluentArrangeContextTests
{
[Fact]
public void WithDependency_DependencyTypeNotFound_ShouldNotCallConfigureDependency()
public void WithDependency_TypeNotFound_ShouldNotInvokeAction()
{
// Arrange
var called = false;
var invoked = false;
var sut = new FluentArrangeContext<object>(new Dictionary<Type, object>());

// Act
sut.WithDependency<IAccountRepository>(e => called = true);
sut.WithDependency<IAccountRepository>(e => invoked = true);

// Assert
called.Should().BeFalse();
invoked.Should().BeFalse();
}

[Fact]
public void WithDependency_DependencyTypeFound_ShouldInvokeConfigureDependency()
public void WithDependency_TypeFound_ShouldInvokeAction()
{
// Arrange
var called = false;
var invoked = false;
var dependencies = new Dictionary<Type, object>
{
{typeof(IAccountRepository), new AccountRepository()}
};
var sut = new FluentArrangeContext<AccountService>(dependencies);

// Act
sut.WithDependency<IAccountRepository>(e => called = true);
sut.WithDependency<IAccountRepository>(e => invoked = true);

// Assert
called.Should().BeTrue();
invoked.Should().BeTrue();
}

[Fact]
public void WithDependency_ShouldReturnReferenceToSut()
public void WithDependency_Type_ShouldReturnReferenceToSut()
{
// Arrange
var sut = new FluentArrangeContext<AccountService>(new Dictionary<Type, object>());
Expand All @@ -57,27 +57,27 @@ public void WithDependency_ShouldReturnReferenceToSut()
}

[Fact]
public void BuildSut_DependencyContainsInstance_BuiltSutShouldContainDependencyInstance()
public void WithDependency_T_InstanceTypeFound_DependenciesShouldContainInstance()
{
// Arrange
var dependency = new AccountRepository();
var dependencies = new Dictionary<Type, object>
{
{typeof(IAccountRepository), dependency}
{typeof(IAccountRepository), new AccountRepository()}
};

var sut = new FluentArrangeContext<AccountService>(dependencies)
.WithDependency<IAccountRepository>(e => { });
var sut = new FluentArrangeContext<AccountService>(dependencies);

var newInstance = new AccountRepository();

// Act
var result = sut.BuildSut();
sut.WithDependency<IAccountRepository>(newInstance);

// Assert
result.AccountRepository.Should().Be(dependency);
sut.Dependencies[typeof(IAccountRepository)].Should().Be(newInstance);
}

[Fact]
public void WithDependency_Instance_DependenciesShouldContainInstance()
public void WithDependency_T_InstanceTypeNotFound_ShouldThrowInvalidOperationException()
{
// Arrange
var dependencies = new Dictionary<Type, object>
Expand All @@ -87,17 +87,36 @@ public void WithDependency_Instance_DependenciesShouldContainInstance()

var sut = new FluentArrangeContext<AccountService>(dependencies);

var newInstance = new AccountRepository();
// Act
Action act = () => sut.WithDependency<IFoo>(new Foo());

// Assert
act.Should().Throw<InvalidOperationException>()
.And.Message.Should().Be("No dependency found of type FluentArrange.Tests.TestClasses.IFoo");
}

[Fact]
public void WithDependency_T2_T3_InstanceTypeFound_ShouldInvokeAction()
{
// Arrange
var dependencies = new Dictionary<Type, object>
{
{typeof(IAccountRepository), new AccountRepository()}
};

var sut = new FluentArrangeContext<AccountService>(dependencies);

var invoked = false;

// Act
sut.WithDependency<IAccountRepository>(newInstance);
sut.WithDependency<IAccountRepository, AccountRepository>(new AccountRepository(), repository => invoked = true);

// Assert
sut.Dependencies[typeof(IAccountRepository)].Should().Be(newInstance);
invoked.Should().BeTrue();
}

[Fact]
public void WithDependency_Instance_TypeNotFound_ShouldThrowInvalidOperationException()
public void WithDependency_T2_T3_InstanceTypeFound_DependenciesShouldContainInstance()
{
// Arrange
var dependencies = new Dictionary<Type, object>
Expand All @@ -107,12 +126,33 @@ public void WithDependency_Instance_TypeNotFound_ShouldThrowInvalidOperationExce

var sut = new FluentArrangeContext<AccountService>(dependencies);

var instance = new AccountRepository();

// Act
Action act = () => sut.WithDependency<IFoo>(new Foo());
sut.WithDependency<IAccountRepository, AccountRepository>(instance, repository => { });

// Assert
act.Should().Throw<InvalidOperationException>()
.And.Message.Should().Be("No dependency found of type FluentArrange.Tests.TestClasses.IFoo");
sut.Dependencies[typeof(IAccountRepository)].Should().Be(instance);
}

[Fact]
public void BuildSut_DependencyContainsInstance_BuiltSutShouldContainDependencyInstance()
{
// Arrange
var dependency = new AccountRepository();
var dependencies = new Dictionary<Type, object>
{
{typeof(IAccountRepository), dependency}
};

var sut = new FluentArrangeContext<AccountService>(dependencies)
.WithDependency<IAccountRepository>(e => { });

// Act
var result = sut.BuildSut();

// Assert
result.AccountRepository.Should().Be(dependency);
}
}
}
8 changes: 4 additions & 4 deletions FluentArrange/FluentArrange.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<Version>0.2.0-alpha</Version>
<Version>0.3.0-alpha</Version>
<Description>Write clean Arrange code using Fluent syntax.</Description>
<PackageProjectUrl>https://github.com/hhoangnl/FluentArrange</PackageProjectUrl>
<RepositoryUrl>https://github.com/hhoangnl/FluentArrange</RepositoryUrl>
<PackageReleaseNotes>Added overloads to accept instances:
- WithDependency&lt;T&gt;(T)
- WithDependency&lt;T&gt;(T, Action&lt;T&gt;)</PackageReleaseNotes>
<PackageReleaseNotes>Added overload to configure and call T2-specific methods:
- WithDependency&lt;T, T2&gt;(T2, Action&lt;T2&gt;)
</PackageReleaseNotes>
<PackageTags>AAA TDD mocking unit-testing</PackageTags>
<Authors>Huy Hoang</Authors>
<Copyright>Huy Hoang</Copyright>
Expand Down
21 changes: 18 additions & 3 deletions FluentArrange/FluentArrangeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ internal FluentArrangeContext(Dictionary<Type, object> dependencies)

public T Sut => _sut ??= BuildSut();

public FluentArrangeContext<T> WithDependency<T2>(Action<T2> configureDependency) where T2 : class
public FluentArrangeContext<T> WithDependency<T2>(Action<T2> configureDependency)
where T2 : class
{
if (Dependencies.TryGetValue(typeof(T2), out var value) && value is T2 dependency)
{
Expand All @@ -31,7 +32,8 @@ public FluentArrangeContext<T> WithDependency<T2>(Action<T2> configureDependency
return this;
}

public FluentArrangeContext<T> WithDependency<T2>(T2 instance) where T2 : class
public FluentArrangeContext<T> WithDependency<T2>(T2 instance)
where T2 : class
{
_ = Dependency<T2>();

Expand All @@ -40,7 +42,20 @@ public FluentArrangeContext<T> WithDependency<T2>(T2 instance) where T2 : class
return this;
}

public FluentArrangeContext<T> WithDependency<T2>(T2 instance, Action<T2> configureInstance) where T2 : class
public FluentArrangeContext<T> WithDependency<T2>(T2 instance, Action<T2> configureInstance)
where T2 : class
{
_ = Dependency<T2>();

Dependencies[typeof(T2)] = instance;
configureInstance(instance);

return this;
}

public FluentArrangeContext<T> WithDependency<T2, T3>(T3 instance, Action<T3> configureInstance)
where T2 : class
where T3 : T2
{
_ = Dependency<T2>();

Expand Down
9 changes: 9 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ var context = Arrange.Sut<ResetPasswordController>()
});
~~~

or `WithDependency<T, T2>(T2, Action<T2>)` if you need to call `T2`-specific methods:
~~~ C#
var context = Arrange.Sut<ResetPasswordController>()
.WithDependency<IAccountService, InMemoryAccountService>(new InMemoryAccountService(), d =>
{
d.AddTestAccounts();
});
~~~

## Asserting Dependencies
Suppose you need to assert that a dependency's method has been called.
Well, you simply arrange code with `Arrange.For<T>` instead of `Arrange.Sut<T>` to get a `FluentArrangeContext` object:
Expand Down