Thursday, September 5, 2019

Unit Test Database Mocking in Golang is Killing Me!


For some reason, writing a particular set of unit tests in Golang proved to be an extreme hassle.  In this case, I was trying to add a column to a table and then write a unit test to verify this new functionality.  No matter how much I looked around for where to correctly specify how to build this table with the new column, the Cassandra database kept complaining the column didn’t exist.  Imagine how frustrating it is to specify a relational database schema that seems to be ignored by your unit tests.

Background


Our system consists of a Cassandra database plus a Go backend server.  The Go unit tests require Cassandra to be running locally on a Docker container, but do not seem to actually utilize the existing databases, opting to make its own that is out of reach from anything I can see from TablePlus.  The Go code itself utilizes these objects through some level of indirection by a manager, a harness, and a couple modules dealing in the actual queries.

The Fix


In the test harness, I was running several commands following the format

CREATE TABLE IF NOT EXISTS table {
column1 boolean,
column2 int
}

Well, turns out that despite my best efforts to define how the table schema was supposed to be set up, the test engine was not actually running the setup every time.  In fact, it was relying on some old cached copy of the tables living somewhere.  Upon changing the command to

DROP TABLE table;
CREATE TABLE table { … }

I was able to see the tests perform correctly on my local machine.  Oddly, in looking for errors upon creation, it would still complain of timeouts on occasion, but overall the functionality appeared correct — the unit test was at least passing.  Interestingly, the QA environment from which we automatically run these tests from a CircleCI pipeline did not need the whole DROP TABLE fix; it worked properly upon simply specifying the correct column configuration in the test harness.

One caveat was that I had to split out the DROP and CREATE statements into separate calls to Session.Query().  When trying to separate them with a semicolon, Go complained it could not execute the statement.

Ultimately, this provided hours of frustration for me in trying to figure out why the unit test would not work locally.  I was afraid the same situation would apply to QA, but fortunately it didn’t.