Skip to content

Commit

Permalink
feat: add DependencyScope utility class
Browse files Browse the repository at this point in the history
  • Loading branch information
jonisavo committed May 11, 2022
1 parent 959f276 commit dd8233a
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 0 deletions.
49 changes: 49 additions & 0 deletions Assets/UIComponents.Tests/DependencyScopeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using NUnit.Framework;
using UIComponents.Utilities;

namespace UIComponents.Tests
{
[TestFixture]
public class DependencyScopeTests
{
public interface IDependency {}

public class DependencyClass : IDependency {}

public class NewDependencyClass : IDependency {}

public class UIComponentWithNoDependencyAttribute : UIComponent
{
public IDependency GetDependency() => Provide<IDependency>();
}

[Dependency(typeof(IDependency), provide: typeof(DependencyClass))]
public class UIComponentWithDependency : UIComponentWithNoDependencyAttribute {}

[Test]
public void Should_Set_Dependency_And_Restore_Previous()
{
var component = new UIComponentWithDependency();

using (new DependencyScope<UIComponentWithDependency, IDependency>(new NewDependencyClass()))
{
Assert.That(component.GetDependency(), Is.InstanceOf<NewDependencyClass>());
}

Assert.That(component.GetDependency(), Is.InstanceOf<DependencyClass>());
}

[Test]
public void Should_Set_Dependency_And_Clear_It_If_No_Previous_Exists()
{
var component = new UIComponentWithNoDependencyAttribute();

using (new DependencyScope<UIComponentWithNoDependencyAttribute, IDependency>(new NewDependencyClass()))
{
Assert.That(component.GetDependency(), Is.InstanceOf<NewDependencyClass>());
}

Assert.Throws<MissingProviderException>(() => component.GetDependency());
}
}
}
3 changes: 3 additions & 0 deletions Assets/UIComponents.Tests/DependencyScopeTests.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Assets/UIComponents/Core/Utilities.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions Assets/UIComponents/Core/Utilities/DependencyScope.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;

namespace UIComponents.Utilities
{
/// <summary>
/// A helper class for setting a dependency temporarily.
/// When disposed, restores the previous provider, or the lack thereof.
/// Built for unit tests.
/// </summary>
/// <typeparam name="TConsumer">Type of the consumer</typeparam>
/// <typeparam name="TDependency">Type of the dependency</typeparam>
public class DependencyScope<TConsumer, TDependency> : IDisposable
where TConsumer : class
where TDependency : class
{
private readonly TDependency _previousDependencyProvider;

public DependencyScope(TDependency instance)
{
var injector = DependencyInjector.GetInjector(typeof(TConsumer));

if (injector.TryProvide<TDependency>(out var currentProvider))
_previousDependencyProvider = currentProvider;

DependencyInjector.SetDependency<TConsumer, TDependency>(instance);
}

public void Dispose()
{
if (_previousDependencyProvider == null)
DependencyInjector.ClearDependency<TConsumer, TDependency>();
else
DependencyInjector.SetDependency<TConsumer, TDependency>(_previousDependencyProvider);
}
}
}
3 changes: 3 additions & 0 deletions Assets/UIComponents/Core/Utilities/DependencyScope.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,28 @@ public void TearDown()
}
```

A `DependencyScope` helper class is available under the `UIComponents.Utilities` namespace.

```c#
[Dependency(typeof(ICounterService), provide: typeof(CounterService))]
public class CounterComponent : UIComponent {}
```
```c#
using UIComponents.Utilities;

[Test]
public void It_Works()
{
var service = new MockCounterService();
using (new DependencyScope<CounterComponent, ICounterService>(service))
{
// MockCounterService will be provided for CounterComponent
}

// CounterService will be provided
}
```

## Loading assets

### Resources
Expand Down

0 comments on commit dd8233a

Please sign in to comment.