SQL Server 2016 RTM shipped last year and most teams are moving to it now. If you have a tSQLt suite — and by this point you should — there are specific things worth verifying before the upgrade touches your test databases. None of them are dealbreakers, but skipping the checks means discovering the issues under pressure rather than on your schedule.
Verify the tSQLt Assembly After Upgrading
tSQLt depends on a CLR assembly. CLR assemblies target a specific .NET runtime version hosted by SQL Server. When you move to a new SQL Server version, the CLR host can change, and older assemblies sometimes need to be reinstalled.
After upgrading a SQL Server instance to 2016, the first thing to do is run a framework-level health check before looking at any test results:
-- Confirm tSQLt framework objects are accessible
SELECT name, type_desc FROM sys.objects WHERE schema_id = SCHEMA_ID('tSQLt')
ORDER BY type_desc, name;
-- Try a framework call
EXEC tSQLt.RunAll;
If the CLR assembly is incompatible with the 2016 host, you'll get an error on framework startup — not on individual tests. Download the current tSQLt release from tsqlt.org before the upgrade and keep it ready. Reinstalling the assembly against the 2016 instance is the fix if you hit this.
Check TRUSTWORTHY After Database Migration
If you're migrating your database to a new 2016 instance via backup/restore rather than in-place upgrade, confirm TRUSTWORTHY survived the migration:
SELECT name, is_trustworthy_on
FROM sys.databases
WHERE name IN ('YourDatabase', 'YourDatabase_CI');
TRUSTWORTHY is a database-level property that can revert to OFF on a restored database in some scenarios. If it's off, tSQLt framework calls fail with permission errors. Restore it:
ALTER DATABASE YourDatabase SET TRUSTWORTHY ON;
New 2016 Features That Interact With FakeTable
Row-Level Security. If you implement RLS on tables that your tests query via FakeTable, be aware that FakeTable creates a new table object — RLS security predicates bound to the original table name do not follow to the fake. Your tests will see unfiltered data. For most unit tests this is correct behavior: you're testing procedure logic, not RLS enforcement. But if you're writing tests specifically for RLS filter functions, you need a different approach — test those through direct queries against the real table in a controlled test environment.
Temporal Tables. System-time temporal tables have hidden PERIOD columns. FakeTable on a temporal table creates a regular (non-temporal) substitute — the temporal audit columns won't be present. For most tests this is fine. If you're testing procedures that query historical data via FOR SYSTEM_TIME AS OF, FakeTable won't give you a queryable history. Test those queries against a real temporal table in a dedicated integration test run, not in your tSQLt unit suite.
Always Encrypted. Columns with Always Encrypted require the column master key available to the connection. Test connections on your CI build agent may not have key access. If your procedures operate on encrypted columns, the simplest unit-testing approach is to isolate the encrypted-column operations into a thin procedure layer and test the business logic separately. Test the encryption integration in a dedicated environment with proper key access.
The Most Common Upgrade Problem
In practice, the most frequent issue when upgrading SQL Server with an existing tSQLt suite isn't the framework itself — it's tests failing because the upgrade changed something real. A query plan changed. A type conversion that worked in 2014 behaves differently in 2016. An implicit conversion that the old cardinality estimator handled one way now produces a different result.
Those test failures are the tests doing their job. Read the failure messages before assuming the framework broke. Usually the upgrade changed something you needed to know about — and now you know before it reaches production. As always, I'm here to help.