Testing your CosmosDB C# code and automating it with AppVeyor
Tags: cosmosdb, azure, appveyor, nosql
Published: 2018-09-17 13:08:29

---
title: Testing your CosmosDB C# code and automating it with AppVeyor
published: true
description: In this blog I will talk about the challenges we face when we are writing unit tests for CosmosDB and how to automate them with AppVeyor.
tags: cosmosdb, azure, appveyor, nosql
---

#### Introduction

Don't we all love well tested code? I know I do.
It's just an awesome feeling knowing that if I change something over here, the thing over there didn't break.

However, when your code depends on a third party library, then you have to hope that the code in that library is easy to work with and easy to test.

If this isn't the first blog of mine that you read then you probably know that I'm working on an open-source ORM for CosmosDB called [Cosmonaut](https://github.com/Elfocrash/Cosmonaut). When I'm using a third party library and its code happens to be opensource then the first thing I do is to go to wherever it's code is hosted and check if there are tests covering it. Nobody wants to use untested code, so I knew when I started that I should cover as many scenarios and cases as possible.

#### Unit testing

The CosmosDB SDK is not as friendly as it could be when it comes to unit testing (and the CosmosDB SDK team knows it, so it will get better).
Normally, the way you would unit test such code would be to mock the calls that would go over the wire and just return the dataset that you want this scenario to return.

However here is a list of things that make it really hard for you to test your code.

##### Problem 1

The `ResourceResponse` class has the constructor that contains the `DocumentServiceResponse` parameter marked as `internal`. This is bad because even though you can create a `ResourceReponse` object from your DTO class you cannot set things like RUs consumed, response code and pretty much anything else because they are all coming from the `ResourceResponseBase` which also has the `DocumentServiceResponse` marked as internal.

##### Solution

To solve this problem you have to somehow set the response headers for the `ResourceResponse`. As you might have guessed already, then only way you can do that is via reflection. Here is an extension method that can convert your generic type object to a `ResourceResponse` and allows you to set the `responseHeaders`.

{% gist https://gist.github.com/Elfocrash/ae6ef0b472ae170a70be4cb183706a34 %}

*This extension method is also part of Cosmonaut*

##### Problem 2

The SDK is using IQueryable in order to build a fluent LINQ query and use it to query your CosmosDB. This LINQ query will be then converted into SQL via an internal LINQ2CosmosDBSQL provider that the SDK comes with. The problem with that is that if you want to mock your `IDocumentClient`'s `CreateDocumentQuery` to return a specific data set based on a LINQ expression then you're in for a ride.

##### Solution

Lets take a look at the code.

{% gist https://gist.github.com/Elfocrash/163d3210204fd661ddf9bff14607a812 %}

As you can see, it needs quite the setup. That's because the `IQueryable` needs to be setup from the ground up or else it won't be properly translated.

##### Problem 3

It's basically the same as Problem 2 but for SQL, which makes it slightly easier because there is no IQueryable to setup.

##### Solution

Almost everything in the code from "Problem 2" is the same. The only differences are between the lines 24-47. You need to replace those with the code below.

{% gist https://gist.github.com/Elfocrash/c9b77c5f41cc0d080acc900939abb840 %}

These 3 are the most common unit testing problems you will face with the CosmosDB SDK. Thankfully the other operations are easier to test, especially if you make use of the `ToResourceResponse` extension method.

**UPDATE**: As I was writing this Microsoft released the 2.0.0 version of the CosmosDB SDK packages and in them they changed the constructors of come classes.

If you are using a post 2.0.0 version of the SDK, here are the extension methods you need.

{% gist https://gist.github.com/Elfocrash/276b6518633338091dc8ec2daaec69b2 %}


#### Integration testing

Unit testing is awesome, but you also want to test your system against a real database. These tests should have a wider scope than the unit-sized context of your unit tests. I won't go in depth on this one because everyone's idea of integration testing seems to be different but what you need to remember is that we are trying to test again the real CosmosDB database.

As you probably know, CosmosDB comes with it's own local emulator. That's great because we can use it to run our integration/system tests against. What's also great is that we can use the same emulator as part of our CI pipeline. 

#### Automating unit and integration testing

I personally use [AppVeyor](https://www.appveyor.com/) because it is incredibly easy to setup and get started, it supports loads of stuff such as Azure services and Nuget building out of the box and it is also free for open source projects.

AppVeyor is as simple to setup as linking your Github account and selecting the repository you want it to run against. Once you set that up it will trigger a build every time you commit code. There are tons of stuff to configure if you want something more specific but in this blog I will just explain how you can setup the CosmosDB emulator in AppVeyor. 

AppVeyor will look for an `appveyor.yml` file in your repository. If it's not there it will use the settings that can be found in the "Configuration" section. Our `appveyor.yml` will be pretty simple. We just want to `dotnet build` and `dotnet test` our code. Before that however we need to install the CosmosDB Emulator on the AppVeyor VM. In order to do that we will need the following powershell script:

{% gist https://gist.github.com/Elfocrash/9eef5ee99052c5fd0da9f4272b618cb0 %}

Now the CosmosDB Emulator is installed and you can enjoy testing against it using the default CosmosDB Emulator url `https://localhost:8081` and the well known key `C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==`.


Here is the final appveyor.yml

{% gist https://gist.github.com/Elfocrash/dd0d8ce654309ac7b51b81abbc794866 %}

Once you set that up, a build will be kicked off every time you commit code in the repository and both unit and integration tests will be run against the local CosmosDB emulator instance.

Happy testing!