public void when_take_or_put_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.TakeOrPut(nameOfThing, () => new given_pocket_extensions());

            sut.Should().Throw <InvalidCastException>("impossible to cast a string to the different type");
        }
        public void when_take_or_put_thing_with_invalid_factory_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.TakeOrPut <string>(nameOfThing, thingFactory: null);

            sut.Should().Throw <ArgumentNullException>().Where(
                exception => exception.ParamName == "thingFactory",
                "null is not a valid thing factory");
        }
        public void when_take_or_put_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.TakeOrPut(name: null, () => "not relevant");

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

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

            sut = () => pocket.TakeOrPut(WhiteSpaceString, () => "not relevant");
            sut.Should().Throw <ArgumentNullException>().Where(
                exception => exception.ParamName == "name",
                "a whitespace is not a valid name");
        }
        public void when_take_or_put_stored_thing_it_should_be_found()
        {
            var           sut             = new ConcurrentPocket();
            const string  nameOfThing     = "name of the thing";
            const string  thingItself     = "the thing itself";
            var           isFactoryCalled = false;
            Func <string> thingFactory    = () =>
            {
                isFactoryCalled = true;
                return(thingItself);
            };

            sut.Put(nameOfThing, thingItself);

            sut.TakeOrPut(nameOfThing, thingFactory).Should().BeSameAs(thingItself, "the thing lies in the pocket");
            isFactoryCalled.Should().BeFalse("the think was already stored in the pocket");
        }
        public void when_take_or_put_thing_from_empty_pocket_it_should_make_thing_put_it_into_pocket_and_return_it()
        {
            var           sut             = new ConcurrentPocket();
            const string  nameOfThing     = "name of the thing";
            const string  thingItself     = "the thing itself";
            var           isFactoryCalled = false;
            Func <string> thingFactory    = () =>
            {
                isFactoryCalled = true;
                return(thingItself);
            };

            var thing = sut.TakeOrPut(nameOfThing, thingFactory);

            sut.GetThings().Count.Should().Be(expected: 1, "the made thing should be stored in the pocket");
            isFactoryCalled.Should().BeTrue("it was an empty pocket and the thing should be made from scratch");
            thing.Should().BeSameAs(thingItself, "exactly this thing was made");
        }