public void Success_QCPipelineAttached() { // Setup var qualityStrategyExpected = QualityStrategy.LinearIncrease; var item = new Item("NewItem", 1, 3, qualityStrategyExpected, ShelfLifeStrategy.Stable); var qualityFactoryMock = new Mock <IQualityAlgorithmFactory>(MockBehavior.Strict); var qcList = new List <IQualityAlgorithm>() { new QualityNeverNegativeAlgorithm() }; // Create a mock that expects the sort of strategy that is represented in the item above var expectedReturn = new LinearIncreaseAlgorithm(); qualityFactoryMock.Setup(f => f.Create(qualityStrategyExpected)) .Returns(expectedReturn); var factory = new QualityPipelineFactory(qualityFactoryMock.Object, qcList); // Execution var result = factory.CreatePipeline(item); // Assert // Since we haven't provided any QC steps, we should have a single element Assert.AreEqual(1 + qcList.Count, result.Count); Assert.AreEqual(expectedReturn, result[0]); for (var i = 0; i < qcList.Count; i++) { Assert.AreEqual(qcList[i], result[1 + i]); } }
public void Failure_ItemIsNull() { // Setup var qualityFactoryMock = new Mock <IQualityAlgorithmFactory>(); var factory = new QualityPipelineFactory(qualityFactoryMock.Object, null); // Execution and assert Assert.ThrowsException <ArgumentNullException>(() => factory.CreatePipeline(null)); }
public void Success_NullListOfQualityControlChecksDoesNotRaiseException() { // Setup var qualityFactoryMock = new Mock <IQualityAlgorithmFactory>(); // Execution var factory = new QualityPipelineFactory(qualityFactoryMock.Object, null); // Assert Assert.IsNotNull(factory); // Not really needed }
public void Failure_FactoryThrowsArgumentException() { // Setup var item = new Item("NewItem", 1, 3, QualityStrategy.Stable, ShelfLifeStrategy.Stable); var qualityFactoryMock = new Mock <IQualityAlgorithmFactory>(); qualityFactoryMock.Setup(f => f.Create(It.IsAny <QualityStrategy>())) .Throws(new ArgumentException()); var factory = new QualityPipelineFactory(qualityFactoryMock.Object, null); // Execution and assert // We'd expect this to result in a GildedRoseException exception Assert.ThrowsException <GildedRoseException>(() => factory.CreatePipeline(item)); }
public void Failure_FactoryThrowsGildedRoseException() { // Setup var item = new Item("NewItem", 1, 3, QualityStrategy.Stable, ShelfLifeStrategy.Stable); var qualityFactoryMock = new Mock <IQualityAlgorithmFactory>(); var expectedException = new GildedRoseException(); qualityFactoryMock.Setup(f => f.Create(It.IsAny <QualityStrategy>())) .Throws(expectedException); var factory = new QualityPipelineFactory(qualityFactoryMock.Object, null); // Execution and assert // We'd expect this to result in the original exception being rethrown var theException = Assert.ThrowsException <GildedRoseException>(() => factory.CreatePipeline(item)); Assert.AreEqual(expectedException, theException); }
public void Success_CorrectPipelineReturned() { // Setup var qualityStrategyExpected = QualityStrategy.Stable; var item = new Item("NewItem", 1, 3, qualityStrategyExpected, ShelfLifeStrategy.Stable); var qualityFactoryMock = new Mock <IQualityAlgorithmFactory>(MockBehavior.Strict); // Create a mock that expects the sort of strategy that is represented in the item above var expectedReturn = new StableQualityAlgorithm(); qualityFactoryMock.Setup(f => f.Create(qualityStrategyExpected)) .Returns(expectedReturn); var factory = new QualityPipelineFactory(qualityFactoryMock.Object, null); // Execution var result = factory.CreatePipeline(item); // Assert // Since we haven't provided any QC steps, we should have a single element Assert.AreEqual(1, result.Count); Assert.AreEqual(expectedReturn, result[0]); }
/// <summary> /// The main program entry point /// </summary> /// <param name="args">Command line arguments</param> static async Task <int> Main(string[] args) { // We require two arguments, one for the input file and the other for the output file. If we don't have these // we must stop if (args.Length != 2) { Console.WriteLine("Usage: GuildedRose InputFileName OutputFileName"); Console.WriteLine("The program will parse the input file, modify the contents and output the result to " + "the output file"); return(-1); } // Creates a mapping between the quality control strategy and the implementation. This uses // type and not a direct instantiation to prevent to prevent more complicated classes interfering with // each other should this algorithm ultimately be paralleled. var qualityAlgorithmFactory = new QualityAlgorithmFactory(new Dictionary <QualityStrategy, Type>() { { QualityStrategy.Stable, typeof(StableQualityAlgorithm) }, { QualityStrategy.LinearDecrease, typeof(LinearDecreaseAlgorithm) }, { QualityStrategy.LinearIncrease, typeof(LinearIncreaseAlgorithm) }, { QualityStrategy.RapidDecrease, typeof(RapidDecreaseAlgorithm) }, { QualityStrategy.IncreasingUntilSellBy, typeof(IncreasingValueUntilSellByAlgorithm) }, }); // Creates a mapping between the shelf life strategy and the implementation. var shelfLifeAlgorithmFactory = new ShelfLifeAlgorithmFactory(new Dictionary <ShelfLifeStrategy, Type>() { { ShelfLifeStrategy.Stable, typeof(StableShelfLifeAlgorithm) }, { ShelfLifeStrategy.LinearDecrease, typeof(LinearDecreaseShelfLifeAlgorithm) } }); // Creates a mapping between an item of stock and it's corresponding stock management strategy. var itemFactory = new ItemFactory(new Dictionary <string, StockManagementStrategy>() { { "Aged Brie", new StockManagementStrategy(QualityStrategy.LinearIncrease, ShelfLifeStrategy.LinearDecrease) }, { "Backstage passes", new StockManagementStrategy(QualityStrategy.IncreasingUntilSellBy, ShelfLifeStrategy.LinearDecrease) }, { "Sulfuras", new StockManagementStrategy(QualityStrategy.Stable, ShelfLifeStrategy.Stable) }, { "Normal Item", new StockManagementStrategy(QualityStrategy.LinearDecrease, ShelfLifeStrategy.LinearDecrease) }, { "Conjured", new StockManagementStrategy(QualityStrategy.RapidDecrease, ShelfLifeStrategy.LinearDecrease) } }); // Define a list of quality control steps that must be run every time var qualityControl = new List <IQualityAlgorithm>() { new QualityNeverNegativeAlgorithm(), new QualityNeverAboveThresholdAlgorithm(50) }; // And now the object that creates the factory for the item. var qualityFactory = new QualityPipelineFactory(qualityAlgorithmFactory, qualityControl); // Create an object that can parse the text. If multiple formats are required this could be created via // a factory object. For now, we only have one format var stringParse = new SpaceSeparatedParser(); // Create the processing object that performs the main business logic var itemProcessor = new ItemProcessor(qualityFactory, shelfLifeAlgorithmFactory); // Create the object that can convert between our parsed item and the real inventory item var itemToInventoryParse = new ParsedItemToInventoryItemConverter(itemFactory); try { // Open the input file await using var inputStream = new FileStream(args[0], FileMode.Open); // Create the output file await using var outputStream = new FileStream(args[1], FileMode.Create); await using var outputStreamWriter = new StreamWriter(outputStream); // Create the object that performs the final output var outputProcessor = new OutputProcessor(outputStreamWriter); // Run the pipeline by awaiting on the observable await create_observable_stream(inputStream, stringParse, itemToInventoryParse, itemProcessor, outputProcessor); Console.WriteLine("File processed."); // The file was processed successfully. We do not consider any parsing errors as significant (since // the output file has been marked accordingly). return(0); } catch (Exception ex) { Console.WriteLine( $"The process could not be completed because an error occurred. Exception: {ex.Message}"); return(-1); } }