using System; using System.Collections.Generic; using System.Threading.Tasks; using Moq; using NUnit.Framework; using WotBlitzStatisticsPro.Logic.Pipeline; using FluentAssertions; namespace WotBlitzStatisticsPro.Tests.PipelineTests { [TestFixture] public class PipelineEngineTest { private readonly Mock _operationFactoryMock = new Mock(); private readonly Mock _firstOperationMock = new Mock(); private readonly Mock _secondOperationMock = new Mock(); [SetUp] public void Init() { _operationFactoryMock.Setup(f => f.Create(typeof(FirstTestOperation))) .Returns(_firstOperationMock.Object); _operationFactoryMock.Setup(f => f.Create(typeof(SecondTestOperation))) .Returns(_secondOperationMock.Object); } [Test] public async Task PipelineShouldBeBuiltAndInvokedCorrectly() { var context = new TestContext(); var pipeline = new Pipeline(_operationFactoryMock.Object); pipeline.AddOperation() .AddOperation(); var callsSequence = new List(); _firstOperationMock.Setup(f => f.Invoke(context, It.IsAny>())) .Callback((TestContext c, Func n) => callsSequence.Add(typeof(FirstTestOperation))) .Returns((TestContext c, Func n) => n.Invoke(c)); _secondOperationMock.Setup(f => f.Invoke(context, It.IsAny>())) .Callback((TestContext c, Func n) => callsSequence.Add(typeof(SecondTestOperation))); await pipeline.Build() .Invoke(context, null) .ConfigureAwait(false); // Check if first operation called first and only once. And second called second and once _firstOperationMock.Verify(f => f.Invoke(context, It.IsAny>()), Times.Once); _secondOperationMock.Verify(f => f.Invoke(context, It.IsAny>()), Times.Once); callsSequence.Count.Should().Be(2); callsSequence[0].Should().Be(typeof(FirstTestOperation)); callsSequence[1].Should().Be(typeof(SecondTestOperation)); } [Test] public async Task PipelineShouldStopIfFirstTaskDoesNotCallNext() { var context = new TestContext(); var pipeline = new Pipeline(_operationFactoryMock.Object); pipeline.AddOperation() .AddOperation(); var callsSequence = new List(); _firstOperationMock.Setup(f => f.Invoke(context, It.IsAny>())) .Callback((TestContext c, Func n) => callsSequence.Add(typeof(FirstTestOperation))) .Returns(Task.CompletedTask); _secondOperationMock.Setup(f => f.Invoke(context, It.IsAny>())) .Callback((TestContext c, Func n) => callsSequence.Add(typeof(SecondTestOperation))); await pipeline.Build() .Invoke(context, null) .ConfigureAwait(false); // Check if first operation called first and only once. And second did not call _firstOperationMock.Verify(f => f.Invoke(context, It.IsAny>()), Times.Once); _secondOperationMock.Verify(f => f.Invoke(context, It.IsAny>()), Times.Never); callsSequence.Count.Should().Be(1); callsSequence[0].Should().Be(typeof(FirstTestOperation)); } } }