Skip to content

Commit

Permalink
Replace CommandContext with factory classes
Browse files Browse the repository at this point in the history
  • Loading branch information
robhruska committed Apr 4, 2017
1 parent e787e52 commit 88642e9
Show file tree
Hide file tree
Showing 12 changed files with 457 additions and 461 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
using Hudl.Mjolnir.Command;
using Hudl.Mjolnir.Bulkhead;
using Hudl.Mjolnir.Config;
using Hudl.Mjolnir.External;
using Hudl.Mjolnir.Key;
using Hudl.Mjolnir.Log;
using Hudl.Mjolnir.Tests.Helper;
using Moq;
using System;
using Xunit;

namespace Hudl.Mjolnir.Tests.Command
namespace Hudl.Mjolnir.Tests.Bulkhead
{
public class CommandContextTests
public class BulkheadFactoryTests
{
public class GetBulkhead : TestFixture
public class GetBulkhead
{
[Fact]
public void ReturnsSameBulkheadForKey()
Expand All @@ -16,11 +21,17 @@ public void ReturnsSameBulkheadForKey()
// of any configuration changes, we should be using the same one through the
// lifetime of the app.

var mockMetricEvents = new Mock<IMetricEvents>(MockBehavior.Strict);
var mockLogFactory = new Mock<IMjolnirLogFactory>(MockBehavior.Strict);
mockLogFactory.Setup(m => m.CreateLog(It.IsAny<Type>())).Returns(new DefaultMjolnirLog());

var bulkheadConfig = new BulkheadConfig(new DefaultValueConfig());

var key = GroupKey.Named(Rand.String());
var context = new CommandContextImpl();
var factory = new BulkheadFactory(mockMetricEvents.Object, bulkheadConfig, mockLogFactory.Object);

var bulkhead = context.GetBulkhead(key);
Assert.Equal(bulkhead, context.GetBulkhead(key));
var bulkhead = factory.GetBulkhead(key);
Assert.Equal(bulkhead, factory.GetBulkhead(key));
}

[Fact]
Expand All @@ -29,10 +40,16 @@ public void DefaultBulkheadSizeIs10()
// This is mainly to ensure we don't introduce a breaking change for clients
// who rely on the default configs.

var mockMetricEvents = new Mock<IMetricEvents>(MockBehavior.Strict);
var mockLogFactory = new Mock<IMjolnirLogFactory>(MockBehavior.Strict);
mockLogFactory.Setup(m => m.CreateLog(It.IsAny<Type>())).Returns(new DefaultMjolnirLog());

var bulkheadConfig = new BulkheadConfig(new DefaultValueConfig());

var key = GroupKey.Named(Rand.String());
var context = new CommandContextImpl();
var factory = new BulkheadFactory(mockMetricEvents.Object, bulkheadConfig, mockLogFactory.Object);

var bulkhead = context.GetBulkhead(key);
var bulkhead = factory.GetBulkhead(key);
Assert.Equal(10, bulkhead.CountAvailable);
}

Expand Down
61 changes: 30 additions & 31 deletions Hudl.Mjolnir.Tests/Command/BreakerInvokerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using Hudl.Mjolnir.Tests.Helper;
using Moq;
using Xunit;
using Hudl.Mjolnir.Bulkhead;

namespace Hudl.Mjolnir.Tests.Command
{
Expand All @@ -21,22 +20,22 @@ public class ExecuteWithBreakerAsync : TestFixture
public async Task WhenRejected_FiresBreakerRejectedMetricEvent()
{
var key = Rand.String();

var mockCommandContext = new Mock<ICommandContext>();

var mockBreaker = new Mock<ICircuitBreaker>();
var mockMetricEvents = new Mock<IMetricEvents>();
var mockMetrics = new Mock<ICommandMetrics>();
mockBreaker.SetupGet(m => m.Name).Returns(key);
mockBreaker.Setup(m => m.IsAllowing()).Returns(false); // We want to reject.
mockBreaker.SetupGet(m => m.Metrics).Returns(mockMetrics.Object);
mockCommandContext.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);
mockCommandContext.SetupGet(m => m.MetricEvents).Returns(mockMetricEvents.Object);

var mockCircuitBreakerFactory = new Mock<ICircuitBreakerFactory>(MockBehavior.Strict);
mockCircuitBreakerFactory.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);

var mockBreakerExceptionHandler = new Mock<IBreakerExceptionHandler>(MockBehavior.Strict);
mockBreakerExceptionHandler.Setup(m => m.IsExceptionIgnored(It.IsAny<Type>())).Returns(false);

var command = new NoOpAsyncCommand();
var invoker = new BreakerInvoker(mockCommandContext.Object, mockBreakerExceptionHandler.Object);
var invoker = new BreakerInvoker(mockCircuitBreakerFactory.Object, mockMetricEvents.Object, mockBreakerExceptionHandler.Object);

await Assert.ThrowsAsync<CircuitBreakerRejectedException>(() => invoker.ExecuteWithBreakerAsync(command, CancellationToken.None));

Expand All @@ -47,22 +46,22 @@ public async Task WhenRejected_FiresBreakerRejectedMetricEvent()
public async Task WhenSuccessful_FiresBreakerSuccessCountMetricEvent()
{
var key = Rand.String();

var mockCommandContext = new Mock<ICommandContext>();

var mockBreaker = new Mock<ICircuitBreaker>();
var mockMetricEvents = new Mock<IMetricEvents>();
var mockMetrics = new Mock<ICommandMetrics>();
mockBreaker.SetupGet(m => m.Name).Returns(key);
mockBreaker.Setup(m => m.IsAllowing()).Returns(true); // We want to get past the initial rejection check.
mockBreaker.SetupGet(m => m.Metrics).Returns(mockMetrics.Object);
mockCommandContext.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);
mockCommandContext.SetupGet(m => m.MetricEvents).Returns(mockMetricEvents.Object);

var mockCircuitBreakerFactory = new Mock<ICircuitBreakerFactory>(MockBehavior.Strict);
mockCircuitBreakerFactory.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);

var mockBreakerExceptionHandler = new Mock<IBreakerExceptionHandler>(MockBehavior.Strict);
mockBreakerExceptionHandler.Setup(m => m.IsExceptionIgnored(It.IsAny<Type>())).Returns(false);

var command = new NoOpFailingAsyncCommand();
var invoker = new BreakerInvoker(mockCommandContext.Object, mockBreakerExceptionHandler.Object);
var invoker = new BreakerInvoker(mockCircuitBreakerFactory.Object, mockMetricEvents.Object, mockBreakerExceptionHandler.Object);

await Assert.ThrowsAsync<ExpectedTestException>(() => invoker.ExecuteWithBreakerAsync(command, CancellationToken.None));

Expand All @@ -73,22 +72,22 @@ public async Task WhenSuccessful_FiresBreakerSuccessCountMetricEvent()
public async Task WhenFailed_FiresBreakerFailureCountMetricEvent()
{
var key = Rand.String();

var mockCommandContext = new Mock<ICommandContext>();

var mockBreaker = new Mock<ICircuitBreaker>();
var mockMetricEvents = new Mock<IMetricEvents>();
var mockMetrics = new Mock<ICommandMetrics>();
mockBreaker.SetupGet(m => m.Name).Returns(key);
mockBreaker.Setup(m => m.IsAllowing()).Returns(true); // We want to get past the initial rejection check.
mockBreaker.SetupGet(m => m.Metrics).Returns(mockMetrics.Object);
mockCommandContext.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);
mockCommandContext.SetupGet(m => m.MetricEvents).Returns(mockMetricEvents.Object);

var mockCircuitBreakerFactory = new Mock<ICircuitBreakerFactory>(MockBehavior.Strict);
mockCircuitBreakerFactory.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);

var mockBreakerExceptionHandler = new Mock<IBreakerExceptionHandler>(MockBehavior.Strict);
mockBreakerExceptionHandler.Setup(m => m.IsExceptionIgnored(It.IsAny<Type>())).Returns(false);

var command = new NoOpAsyncCommand(); // Should be successful.
var invoker = new BreakerInvoker(mockCommandContext.Object, mockBreakerExceptionHandler.Object);
var invoker = new BreakerInvoker(mockCircuitBreakerFactory.Object, mockMetricEvents.Object, mockBreakerExceptionHandler.Object);

await invoker.ExecuteWithBreakerAsync(command, CancellationToken.None);

Expand All @@ -102,22 +101,22 @@ public class ExecuteWithBreaker : TestFixture
public void WhenRejected_FiresBreakerRejectedMetricEvent()
{
var key = Rand.String();

var mockCommandContext = new Mock<ICommandContext>();

var mockBreaker = new Mock<ICircuitBreaker>();
var mockMetricEvents = new Mock<IMetricEvents>();
var mockMetrics = new Mock<ICommandMetrics>();
mockBreaker.SetupGet(m => m.Name).Returns(key);
mockBreaker.Setup(m => m.IsAllowing()).Returns(false); // We want to reject.
mockBreaker.SetupGet(m => m.Metrics).Returns(mockMetrics.Object);
mockCommandContext.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);
mockCommandContext.SetupGet(m => m.MetricEvents).Returns(mockMetricEvents.Object);

var mockCircuitBreakerFactory = new Mock<ICircuitBreakerFactory>(MockBehavior.Strict);
mockCircuitBreakerFactory.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);

var mockBreakerExceptionHandler = new Mock<IBreakerExceptionHandler>(MockBehavior.Strict);
mockBreakerExceptionHandler.Setup(m => m.IsExceptionIgnored(It.IsAny<Type>())).Returns(false);

var command = new NoOpCommand();
var invoker = new BreakerInvoker(mockCommandContext.Object, mockBreakerExceptionHandler.Object);
var invoker = new BreakerInvoker(mockCircuitBreakerFactory.Object, mockMetricEvents.Object, mockBreakerExceptionHandler.Object);

Assert.Throws<CircuitBreakerRejectedException>(() => invoker.ExecuteWithBreaker(command, CancellationToken.None));

Expand All @@ -128,22 +127,22 @@ public void WhenRejected_FiresBreakerRejectedMetricEvent()
public void WhenSuccessful_FiresBreakerSuccessCountMetricEvent()
{
var key = Rand.String();

var mockCommandContext = new Mock<ICommandContext>();

var mockBreaker = new Mock<ICircuitBreaker>();
var mockMetricEvents = new Mock<IMetricEvents>();
var mockMetrics = new Mock<ICommandMetrics>();
mockBreaker.SetupGet(m => m.Name).Returns(key);
mockBreaker.Setup(m => m.IsAllowing()).Returns(true); // We want to get past the initial rejection check.
mockBreaker.SetupGet(m => m.Metrics).Returns(mockMetrics.Object);
mockCommandContext.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);
mockCommandContext.SetupGet(m => m.MetricEvents).Returns(mockMetricEvents.Object);

var mockCircuitBreakerFactory = new Mock<ICircuitBreakerFactory>(MockBehavior.Strict);
mockCircuitBreakerFactory.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);

var mockBreakerExceptionHandler = new Mock<IBreakerExceptionHandler>(MockBehavior.Strict);
mockBreakerExceptionHandler.Setup(m => m.IsExceptionIgnored(It.IsAny<Type>())).Returns(false);

var command = new NoOpFailingCommand();
var invoker = new BreakerInvoker(mockCommandContext.Object, mockBreakerExceptionHandler.Object);
var invoker = new BreakerInvoker(mockCircuitBreakerFactory.Object, mockMetricEvents.Object, mockBreakerExceptionHandler.Object);

Assert.Throws<ExpectedTestException>(() => invoker.ExecuteWithBreaker(command, CancellationToken.None));

Expand All @@ -154,22 +153,22 @@ public void WhenSuccessful_FiresBreakerSuccessCountMetricEvent()
public void WhenFailed_FiresBreakerFailureCountMetricEvent()
{
var key = Rand.String();

var mockCommandContext = new Mock<ICommandContext>();

var mockBreaker = new Mock<ICircuitBreaker>();
var mockMetricEvents = new Mock<IMetricEvents>();
var mockMetrics = new Mock<ICommandMetrics>();
mockBreaker.SetupGet(m => m.Name).Returns(key);
mockBreaker.Setup(m => m.IsAllowing()).Returns(true); // We want to get past the initial rejection check.
mockBreaker.SetupGet(m => m.Metrics).Returns(mockMetrics.Object);
mockCommandContext.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);
mockCommandContext.SetupGet(m => m.MetricEvents).Returns(mockMetricEvents.Object);

var mockCircuitBreakerFactory = new Mock<ICircuitBreakerFactory>(MockBehavior.Strict);
mockCircuitBreakerFactory.Setup(m => m.GetCircuitBreaker(It.IsAny<GroupKey>())).Returns(mockBreaker.Object);

var mockBreakerExceptionHandler = new Mock<IBreakerExceptionHandler>(MockBehavior.Strict);
mockBreakerExceptionHandler.Setup(m => m.IsExceptionIgnored(It.IsAny<Type>())).Returns(false);

var command = new NoOpCommand(); // Should be successful.
var invoker = new BreakerInvoker(mockCommandContext.Object, mockBreakerExceptionHandler.Object);
var invoker = new BreakerInvoker(mockCircuitBreakerFactory.Object, mockMetricEvents.Object, mockBreakerExceptionHandler.Object);

invoker.ExecuteWithBreaker(command, CancellationToken.None);

Expand Down

0 comments on commit 88642e9

Please sign in to comment.