public void when_try_to_take_stored_thing_by_name_and_its_parent_type_it_should_return_it_and_success_status()
        {
            var          sut         = new ConcurrentPocket();
            const string nameOfThing = "name of the thing";
            var          thingItself = new Derived();

            sut.Put(nameOfThing, thingItself);

            sut.TryTake <Base>(nameOfThing, out var foundThing).Should().BeTrue("the requested thing lies in the pocket");
            foundThing.Should().BeSameAs(thingItself, "thing should be stored by reference");
        }
        public void when_try_to_take_missing_struct_thing_it_should_return_default_value_and_fail_status()
        {
            var          sut         = new ConcurrentPocket();
            const string nameOfThing = "name of the thing";
            var          thingItself = DateTime.Now;

            sut.Put(nameOfThing, thingItself);

            sut.TryTake <DateTime>("a different name", out var foundThing).Should().BeFalse("there is no a thing with this name in the pocket");
            foundThing.Should().Be(new DateTime(), "default DateTime is expected 'nothing' for a struct DateTime");
        }
        public void when_try_to_take_missing_reference_thing_it_should_return_null_and_fail_status()
        {
            var          sut         = new ConcurrentPocket();
            const string nameOfThing = "name of the thing";
            const string thingItself = "the thing itself";

            sut.Put(nameOfThing, thingItself);

            sut.TryTake <string>("a different name", out var foundThing).Should().BeFalse("there is no a thing with this name in the pocket");
            foundThing.Should().BeNull("null is expected 'nothing' for a reference type");
        }
        public void when_try_to_take_stored_thing_with_unexpected_type_it_should_throw()
        {
            var          pocket      = new ConcurrentPocket();
            const string nameOfThing = "name of the thing";
            const string thingItself = "the thing itself";

            pocket.Put(nameOfThing, thingItself);

            Action sut = () => pocket.TryTake <DateTime>(nameOfThing, out _);

            sut.Should().Throw <InvalidCastException>("impossible to cast a string to the different type");
        }
        public void when_try_to_take_thing_with_invalid_name_given_it_should_throw()
        {
            var          pocket      = new ConcurrentPocket();
            const string nameOfThing = "name of the thing";
            const string thingItself = "the thing itself";

            pocket.Put(nameOfThing, thingItself);

            Action sut = () => pocket.TryTake <string>(name: null, out var _);

            sut.Should().Throw <ArgumentNullException>().Where(
                exception => exception.ParamName == "name",
                "null is not a valid name");

            sut = () => pocket.TryTake <string>(string.Empty, out var _);
            sut.Should().Throw <ArgumentNullException>().Where(
                exception => exception.ParamName == "name",
                "an empty string is not a valid name");

            sut = () => pocket.TryTake <string>(WhiteSpaceString, out var _);
            sut.Should().Throw <ArgumentNullException>().Where(
                exception => exception.ParamName == "name",
                "a whitespace is not a valid name");
        }