public void Event_animal_action_updates_the_animal()
        {
            // Arrange
            const int startingAttributeValue = 27;
            var       animal = new Animal
            {
                Id         = "AnimalId",
                Name       = "Snowball",
                UserId     = "UserId",
                TypeId     = "PigId",
                Attributes = new Dictionary <string, decimal>
                {
                    { "Hunger", startingAttributeValue }
                },
                LastCalculated = new DateTime(2018, 5, 1)
            };

            var ruleset = Build.Ruleset("BaseRuleset")
                          .WithAnimalType(animal.TypeId)
                          .HavingAttribute(animal.Attributes.First().Key, ratio: 10)
                          .And.WithAnimalAction("FeedId")
                          .HavingAttributeEffect(animal.Attributes.First().Key, -20)
                          .And.Finish;

            var e = new AnimalActionEvent
            {
                EventId        = "EventId",
                ActingUserId   = animal.UserId,
                OwnerUserId    = animal.UserId,
                AnimalId       = animal.Id,
                AnimalActionId = ruleset.AnimalActions.First().Key,
                Time           = animal.LastCalculated.AddMinutes(1)
            };

            Animal updatedAnimal = null;
            Action <ITransaction, Animal> setNewAnimal = (tx, a) => updatedAnimal = a;

            _rulesetRepositoryMock.Setup(_ => _.ByIdAsync(It.IsAny <ITransaction>(), ruleset.Id, ruleset.Id)).ReturnsAsync(ruleset);
            _animalRepositoryMock.Setup(_ => _.ByIdAsync(It.IsAny <ITransaction>(), e.OwnerUserId, e.AnimalId)).ReturnsAsync(animal);
            _animalRepositoryMock.Setup(_ => _.UpsertAsync(It.IsAny <ITransaction>(), It.IsAny <Animal>())).Callback(setNewAnimal)
            .Returns(Task.CompletedTask);

            var client        = CreateTestClient();
            var stringContent = new StringContent(JsonConvert.SerializeObject(e), Encoding.UTF8, "application/json");

            // Act
            HttpResponseMessage response = client.PutAsync($"event", stringContent).GetAwaiter().GetResult();

            // Assert
            response.EnsureSuccessStatusCode();

            Assert.NotNull(updatedAnimal);
            Assert.Equal(e.AnimalId, updatedAnimal.Id);
            var expectedAttributeValue = startingAttributeValue
                                         + ruleset.AnimalTypes[animal.TypeId].Attributes.First().Value.RatioPerMinute
                                         + ruleset.AnimalActions[e.AnimalActionId].AttributeEffects.First().Value;

            Assert.Equal(expectedAttributeValue, updatedAnimal.Attributes.First().Value);
            Assert.Equal(e.Time, updatedAnimal.LastCalculated);
        }
        public void Appply_applies_the_modifier_for_a_single_attribute_action
            (decimal initialValue, decimal effect, decimal expectedValue,
                decimal minValue = 0, decimal maxValue = 100)
        {
            // Arrange
            const string animalId = "AnimalId";
            const string animalTypeId = "AnimalTypeId";
            const string attributeId = "AttributeId";
            const string animalActionId = "AnimalActionId";

            var animal = new Animal
            {
                Id = animalId,
                TypeId = animalTypeId,
                Attributes = new Dictionary<string, decimal>
                {
                    { attributeId, initialValue }
                }
            };

            var ruleset = Build.Ruleset()
                .WithAnimalAction(animalActionId)
                    .HavingAttributeEffect(attributeId, effect)
                .And.WithAnimalType(animalTypeId)
                    .HavingAttribute(attributeId, minValue: minValue, maxValue: maxValue)
                .And.Finish;

            var target = new AnimalActionEventHandler();

            AnimalActionEvent e = new AnimalActionEvent { AnimalId = animalId, AnimalActionId = animalActionId };

            // Act
            target.Apply(e, new MockAnimalEventContext(animal, ruleset));

            // Assert
            Assert.Equal(expectedValue, animal.Attributes[attributeId]);
        }