tSQLt 应用 NOT NULL 约束

tSQLt apply NOT NULL constraint

如何将 NOT NULL 约束应用回 tSQLt 中的 table 列?

CREATE OR ALTER PROCEDURE [test abc].[test abc1]
AS
BEGIN
    -- Arrange
    EXEC tSQLt.FakeTable 'dbo', 'table1';
    -- Here the NOT NULL constraint should be put back on table1 column col1
    EXEC [tSQLt].[ExpectNoException]
    -- Act + Assert
    INSERT INTO .....
END
GO

尝试以下操作:

UPDATE MYTABLE
SET MyColumn = 'Default Value'
WHERE MyColumn IS NULL

ALTER TABLE MYTABLE
AlTER COLUMN MyColumn DATATYPE NOT NULL

OP 具体询问如何在 tSQLt 单元测试的上下文中执行此操作。

对于那些不知道的人,tSQLt.FakeTable 暂时用具有相同架构、table 和列名以及所有相同数据的模拟替换真实的 table类型但 none 的约束。因此所有列都允许 NULL,并且在测试期间删除所有键、默认值、检查约束甚至 IDENTITY 属性。这在针对具有许多依赖项的单个 table 编写单元测试时非常有用 - 它最大限度地减少了每个测试所需的设置。在每个测试结束时,该测试具有 运行 的事务将回滚并返回原始 table 结构。

现在是实际问题,而 tSQLt.Fake table 确实允许在模拟中保留原始 table 的某些功能,包括自动递增、计算列和默认约束,可空性不是这些功能之一。尽管如果@SebastianMeine 或@dennislloydjr 正在阅读这篇文章,这样的功能可能是有用的增值。

我认为没有自动方法可以将 NOT NULL 应用于伪造的 table 中的列,但它确实引发了有关您的用例的问题。虽然 FakeTable 在许多测试场景中非常有用,但在某些情况下,您可能希望 运行 对真实 table 进行一项或多项测试。这里最明显的例子是一个存储过程,旨在向 table 插入一个新行。如果在写入插入存储过程后将新的 NOT NULL 列添加到 table,则该过程将失败,因为它没有将值插入到新的强制列中。您肯定希望在测试中选择它,并且至少对该存储过程进行一次针对真实 table 的测试,以便在您投入生产之前检测到该错误。

如果您的用例需要仅将特定列设置回 NOT NULL,那么您可以在调用 tSQLt.FakeTable 后手动执行此操作 UPDATE myTable ALTER COLUMN myColumn <datatype> NOT NULL 尽管该方法的危险在于如果数据该列的类型或可空性在将来发生变化,您将无法自动更改测试中的列定义 - 这会降低测试的可靠性。

很抱歉您的问题没有简单的答案。

在 tSQLt 测试中丢失 NULLability 应该不是问题。您可以控制放置在伪造 table 中的数据。您可以确保填充需要正确测试值的列。通过在测试执行期间更改列来更改伪造的 table 的特征会使测试的长期维护变得更加困难。

您可以创建一个重载原始版本的 FakeTable 私有版本。这样您就可以自动恢复 NULLability 设置。 (我们有一个相当广泛的扩展架构,可以重载 FakeTable 并实现许多其他内部功能,而无需更改基本产品。)缺点是现在您必须在填充测试数据时考虑所有 NOT NULL 列,这就是 FakeTable部分是为了避免。使所有列都可为 NULL 允许您将测试重点放在对该测试上下文重要的列上。

您没有说明为什么要恢复可空性设置。知道这一点会改善任何答案。