tSQLt-org / tSQLt

The official tSQLt repository. (Download at: http://tSQLt.org/downloads )
http://tSQLt.org
413 stars 102 forks source link

FakeFunction fails if function is used as a column default #162

Open TheAceMan opened 2 years ago

TheAceMan commented 2 years ago

Receive this error:

[DefaultColumnFunction].[Test fails] failed: (Error) Message: A .NET Framework error occurred during execution of user-defined routine or aggregate "SuppressOutput":
System.Data.SqlClient.SqlException: Object '[dbo].[GetDefaultValue]' cannot be renamed because the object participates in enforced dependencies.
System.Data.SqlClient.SqlException:
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnectionSmi.EventSink.DispatchMessages(Boolean ignoreNonFatalMessages)
   at System.Data.SqlClient.SqlDataReaderSmi.InternalNextResult(Boolean ignoreNonFatalMessages)
   at System.Data.SqlClient.SqlDataReaderSmi.NextResult()
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderSmi(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
   at tSQLtCLR.TestDatabaseFacade.executeCommand(SqlString Command)
   at tSQLtCLR.StoredProcedures.SuppressOutput(SqlString command)
. | Procedure: tSQLt.SuppressOutput (0) | Severity, State: 16, 1 | Number: 6522

Script that reproduces the issue:

CREATE FUNCTION dbo.GetDefaultValue()
RETURNS INT
AS
BEGIN
       RETURN 1;
END
GO
CREATE TABLE dbo.DefaultColumnTable (DefaultColumn int DEFAULT dbo.GetDefaultValue())
GO
EXEC tSQLt.NewTestClass 'DefaultColumnFunction';
GO
CREATE FUNCTION DefaultColumnFunction.Fake_GetDefaultValue()
RETURNS INT
AS
BEGIN
       RETURN 1;
END
GO
CREATE PROCEDURE DefaultColumnFunction.[Test fails]
AS
BEGIN
       EXEC tSQLt.FakeFunction @FunctionName = 'dbo.GetDefaultValue', @FakeFunctionName = '[DefaultColumnFunction].Fake_GetDefaultValue';
END;
GO
EXEC tSQLt.RunTestClass 'DefaultColumnFunction';
GO
EXEC tSQLt.DropClass 'DefaultColumnFunction';
GO
DROP TABLE dbo.DefaultColumnTable
GO
DROP FUNCTION dbo.GetDefaultValue
mbt1 commented 2 years ago

The reason this is not working is the same reason for which faking schema-bound objects is not currently supported.

In short, to make this work we would have to identify and remove all "enforced dependencies", then fake the function, and afterward restore the dependencies (potentially with a switch to make the restore optional). We would also need to provide a way to restore all dependencies in case the test got executed without a transaction (intentionally or unintentionally).

We have started the work on that bigger schema-bound feature, but there is currently no ETA. I'll mark this request as "help wanted".