TCR - more cosmos

TCR - more cosmos

The hilarious thing I realized after doing the last session... I don't think I need CosmosAccountName... OH WELL...

I do need CosmosCollectionName; so let's use our cheat test base and make that.

... forgot to start the script again... I love that I wait for the sound.

Following the recipie to move the class and it's created!

The BULK

OK... so... The next step is gonna be a bit of a big lift. Looking at a previously implemented bit; I need to create a CosmosContainerAdapter which houses a lot of the cosmos interactions. WHich in my examples I don't do a great segregtion of concepts. So... gonna do that here. Which should make for an easier to test implementation.

OK.. I'm gonna first do the scribe; so I first need a CosmosContainerUpsertAdapter.

I created the "Exists" test... then I paused it and moved the files.
I get the strict steps... but... uhh... lazy.

And... as I look at my refernece... yeah... Kinda cheating. :)

ANYWAY - as I look at it; there's a return type I want to use, so I need to TDD that first.

It's a CosmosItemResponse<T>; which basically performs similar behavior to the cosmos ItemResponse<T> but; I don't want 3rd party SDKs scattered through my code.
This is gonna be a ToSystemType that has some aditional behaviors. I'm gonna use the base class created for these.

I'm pausing for moving classes now. It's ... less annoying. I like to know how to do the dance; but doesn't mean we have to do it every time.

I added this test

    [TestMethod, TestCategory("unit")]
    public void Value_PropertyShouldExist()
    {
        //arrange
        CosmosItemResponse<object> subject = new TestCosmosItemResponse<object>();

        //act
        object _ = subject.Value;

        //assert
    }

to let the tool create the Value property for me. I want it to be get only; and it gave me an option to do that. Should I use it; or should I later add a test to force that change?
I'm opting for the later force; but it's an interesting question.

Hrm... it's barfing on me;

... because I short cut'd and the ToSystemType aspect of the CosmosItemResponse is borked... I took shortcuts... don't take shortcuts.

OK; it's pause-fixed. Now I need to overide the Value property; which... uhh... can't... really... soo... I need to make it virtual to implement; then abstract.

Couple tests later and have that. Now I need the same abstract dance with a StatusCode.

I'm wondering how it'll feel to do that with just the "ShouldBeAbstract" test. Ewwww... I don't like it. I can't have the tools create it for me through reflection.
I am seeing how it feels to default create it as abstract...

It feels dirty. That's code there's no test driving it. Removed.

Seeing what happens if I try to go straight to Abstract. Should break.

Yep. My test impl doesn't have the method, so it breaks.

Doing the same few tests.

I know reading this is boring. I'm just typing out my experience with TCR as I'm doing it. I'm sure I'll give a few talks about it; but I don't know what's gonna happen and ... I don't wanna make a big production with this. It's a focus on TCR, not blogging, to get a reasonable system fully implemented with TCR.

Now I need a method to determine if the status code is a success.

The tests I'm starting with for functionality are


    [TestMethod, TestCategory("unit")]
    public void IsSuccessfulStatusCode_ShouldReturnTrueFor200()
    {
        //arrange
        CosmosItemResponse<object> subject = new TestCosmosItemResponse<object>(null, HttpStatusCode.OK);

        //act
        bool actual = subject.IsSuccessfulStatusCode();

        //assert
        _ = actual.Should().BeTrue();
    }

    [TestMethod, TestCategory("unit")]
    public void IsSuccessfulStatusCode_ShouldReturnFalseFor199()
    {
        //arrange
        CosmosItemResponse<object> subject = new TestCosmosItemResponse<object>(null, (HttpStatusCode)199);

        //act
        bool actual = subject.IsSuccessfulStatusCode();

        //assert
        _ = actual.Should().BeFalse();
    }

which is testing the two side of the lower boundary.

I added this for the upper bound



    [TestMethod, TestCategory("unit")]
    public void IsSuccessfulStatusCode_ShouldReturnTrueFor299()
    {
        //arrange
        CosmosItemResponse<object> subject = new TestCosmosItemResponse<object>(null, (HttpStatusCode)299);

        //act
        bool actual = subject.IsSuccessfulStatusCode();

        //assert
        _ = actual.Should().BeTrue();
    }

and it insta-passed.
Which... DUH given


    public bool IsSuccessfulStatusCode()
    {
        return 200 <= (int)StatusCode;
    }

So... I need the failure case first.



    [TestMethod, TestCategory("unit")]
    public void IsSuccessfulStatusCode_ShouldReturnFalseFor300()
    {
        //arrange
        CosmosItemResponse<object> subject = new TestCosmosItemResponse<object>(null, (HttpStatusCode)300);

        //act
        bool actual = subject.IsSuccessfulStatusCode();

        //assert
        _ = actual.Should().BeFalse();
    }

all's fair


    public bool IsSuccessfulStatusCode()
    {
        if ((int)StatusCode == 300) return false;
        return 200 <= (int)StatusCode;
    }

NOW we do the 299 cause.... which still passes. Whatever. Now I'll just fix it.
Don't do this; triangulate!

I have the boundary conditions... I could triangulate... fine... I will add a 500.

Added; then generalized.

public bool IsSuccessfulStatusCode() => 200 <= (int)StatusCode && (int)StatusCode <= 299;

I like having the negated version of a lot of booleans so I can write my code in a way it reads properly... mostly to avoid the ! for turning "false" to "true". Too small.

If you look closely at some commits; you can see more not-triangulating.

The last bit is actually implementing the AsSystemType to return the Value

I am usin copilot a lot for quick reflection tests.

Letting copilot document it for me gives me


/// <summary>
/// Represents a response from a Cosmos DB item operation.
/// </summary>
/// <typeparam name="T">The type of the item.</typeparam>
public abstract class CosmosItemResponse<T> : ToSystemType<T>
{
    /// <summary>
    /// Gets the value of the item.
    /// </summary>
    public abstract T Value { get; }

    /// <summary>
    /// Gets the HTTP status code of the response.
    /// </summary>
    public abstract HttpStatusCode StatusCode { get; }

    /// <summary>
    /// Determines whether the status code indicates a successful response.
    /// </summary>
    /// <returns><c>true</c> if the status code is between 200 and 299; otherwise, <c>false</c>.</returns>
    public bool IsSuccessfulStatusCode() => 200 <= (int)StatusCode && (int)StatusCode <= 299;

    /// <summary>
    /// Determines whether the status code indicates an unsuccessful response.
    /// </summary>
    /// <returns><c>true</c> if the status code is not between 200 and 299; otherwise, <c>false</c>.</returns>
    public bool IsNotSuccessfulStatusCode() => IsSuccessfulStatusCode() is false;

    /// <summary>
    /// Converts the response to its system type representation.
    /// </summary>
    /// <returns>The value of the item.</returns>
    public override T AsSystemType() => Value;
}

My next thing... I think... is the Upserter... which if I follow my current design is gonna require a ContainerFake. We can argue about it being a Fake,Spy,Mock,Bleep,Bloop,Blort. It's a TestDouble; and I'm using a 'Fake' suffix for it.

AND fighting updates... RIGHT... I wanted to add the cosmoslib...

It's late; last test to make sure the container is called.

It's still giving me build issues... BOOOOO.

ANNNNNNNDDDDDD - I'm too tired to continue. I know when I hit that limit. This is still fun. Gotta recreate some base level stuff I never touch anymore... 'cause I created it already. But it's a fun exercise.

Show Comments