Saya sedang belajar menulis unit test untuk bekerja. Saya disarankan untuk menggunakan TSQLT FakeTable untuk menguji beberapa aspek dari tabel yang dibuat oleh prosedur tersimpan.

Dalam pengujian unit lainnya, kami membuat tabel temp untuk prosedur tersimpan dan kemudian menguji tabel temp. Saya tidak yakin bagaimana cara mengerjakan FakeTable ke dalam pengujian.

EXEC tSQLt.NewTestClass 'TestThing'; 
GO                                                 
CREATE OR ALTER PROCEDURE TestThing.[test API_StoredProc to make sure parameters work] 
AS 
BEGIN
    DROP TABLE IF EXISTS #Actual;
    CREATE TABLE #Actual   ----Do I need to create the temp table and the Fake table? I thought I  might need to because I'm testing a table created by a stored procedure.
    ( 
        ISO_3166_Alpha2 NVARCHAR(5),
        ISO_3166_Alpha3 NVARCHAR(5),
        CountryName NVARCHAR(100),
        OfficialStateName NVARCHAR(300),
        sovereigny NVARCHAR(75),
        icon NVARCHAR(100)
    );
    INSERT #Actual
    (
        ISO_3166_Alpha2,
        ISO_3166_Alpha3,
        CountryName,
        OfficialStateName,
        sovereigny,
        icon
    )


    EXEC Marketing.API_StoredProc @Username = 'AnyValue',                              -- varchar(100)
                                                 @FundId = 0,                                 -- int
                                                 @IncludeSalesForceInvestorCountry = NULL,    -- bit
                                                 @IncludeRegisteredSalesJurisdictions = NULL, -- bit
                                                 @IncludeALLCountryForSSRS = NULL,            -- bit
                                                 @WHATIF = NULL,                              -- bit
                                                 @OUTPUT_DEBUG = NULL                         -- bit


   EXEC tsqlt.FakeTable @TableName = N'#Actual',        -- nvarchar(max)  -- How do I differentiate between the faketable and the temp table now? 
                        @SchemaName = N'',       -- nvarchar(max)
                        @Identity = NULL,        -- bit
                        @ComputedColumns = NULL, -- bit
                        @Defaults = NULL         -- bit

  INSERT INTO #Actual 
  (
        ISO_3166_Alpha2,
        ISO_3166_Alpha3,
        CountryName,
        OfficialStateName,
        sovereigny,
        icon
    )
    VALUES 
      ('AF', 'AFG', 'Afghanistan', 'The Islamic Republic of Afghanistan', 'UN MEMBER STATE', 'test')

SELECT * FROM #actual 

END;
GO
EXEC tSQLt.Run 'TestThing';

Apa yang saya coba lakukan dengan kode di atas pada dasarnya hanya untuk membuat FakeTable berfungsi. Saya mendapatkan kesalahan: "FakeTable tidak dapat menyelesaikan nama objek #Actual"

Apa yang akhirnya ingin saya uji adalah paramater dalam prosedur tersimpan. Hanya entri tertentu yang harus dikembalikan jika, misalnya, IncludeSalesForceInvestorCountry disetel ke 1. Apa yang harus dikembalikan dapat berubah seiring waktu, jadi itulah mengapa saya disarankan untuk menggunakan FakeTable.

1
PolarVortex8 22 April 2020, 22:02

1 menjawab

Jawaban Terbaik

Dalam skenario Anda, Anda tidak perlu memalsukan tabel temp, cukup memalsukan tabel yang dirujuk oleh Marketing.API_StoredProc dan mengisinya dengan nilai yang Anda harapkan akan dikembalikan, dan beberapa tidak. Tambahkan apa yang ingin Anda lihat dalam tabel #expected, panggil Marketing.API_StoredProc dengan membuang hasil ke tabel #aktual dan bandingkan hasilnya dengan tSQLt.AssertEqualsTable.

Titik awal yang baik mungkin untuk meninjau cara kerja tSQLT.FakeTable dan kasus penggunaan dunia nyata.

Seperti yang Anda ketahui, setiap pengujian unit berjalan dalam transaksinya sendiri yang dimulai dan dibatalkan oleh kerangka kerja tSQLT. Saat Anda memanggil tSQLt.FakeTable dalam pengujian unit, itu untuk sementara mengganti nama tabel yang ditentukan kemudian membuat faksimili bernama persis dari tabel itu. Salinan sementara memungkinkan NULL di setiap kolom, tidak memiliki kunci utama atau asing, kolom identitas, cek, default atau batasan unik (walaupun beberapa di antaranya dapat dimasukkan dalam tabel faksimili tergantung pada parameter yang diteruskan ke tSQLt.FakeTable). Selama transaksi uji coba, objek apa pun yang mereferensikan tabel nama akan menggunakan tabel palsu daripada tabel asli. Di akhir pengujian, tSQLt mengembalikan transaksi, tabel palsu dijatuhkan dan tabel asli dikembalikan ke keadaan semula (ini semua terjadi secara otomatis). Anda mungkin bertanya, apa gunanya itu?

Bayangkan Anda memiliki tabel [OrderDetail] yang memiliki kolom termasuk OrderId dan ProductId sebagai kunci utama, kolom OrderStatusId ditambah sekelompok kolom NOT NULL lainnya. DDL untuk tabel ini mungkin terlihat seperti ini.

CREATE TABLE [dbo].[OrderDetail]
(
  OrderDetailId int IDENTITY(1,1) NOT NULL
, OrderId int NOT NULL
, ProductId int NOT NULL
, OrderStatusId int NOT NULL
, Quantity int NOT NULL
, CostPrice decimal(18,4) NOT NULL
, Discount decimal(6,4) NOT NULL
, DeliveryPreferenceId int NOT NULL
, PromisedDeliveryDate datetime NOT NULL
, DespatchDate datetime NULL
, ActualDeliveryDate datetime NULL
, DeliveryDelayReason varchar(500) NOT NULL
/* ... other NULL and NOT NULL columns */
, CONSTRAINT PK_OrderDetail PRIMARY KEY CLUSTERED (OrderId, ProductId)
, CONSTRAINT AK_OrderDetail_AutoIncrementingId UNIQUE NONCLUSTERED (OrderDetailId)
, CONSTRAINT FK_OrderDetail_Order FOREIGN KEY (OrderId) REFERENCES [dbo].[Orders] (OrderId)
, CONSTRAINT FK_OrderDetail_Product FOREIGN KEY (ProductId) REFERENCES [dbo].[Product] (ProductId)
, CONSTRAINT FK_OrderDetail_OrderStatus FOREIGN KEY (OrderStatusId) REFERENCES [dbo].[OrderStatus] (OrderStatusId)
, CONSTRAINT FK_OrderDetail_DeliveryPreference FOREIGN KEY (DeliveryPreferenceId) REFERENCES [dbo].[DeliveryPreference] (DeliveryPreferenceId)
);

Seperti yang Anda lihat, tabel ini memiliki dependensi kunci asing pada tabel Orders, Product, DeliveryPreference, dan OrderStatus. Produk pada gilirannya mungkin memiliki kunci asing yang mereferensikan ProductType, BrandCategory, Supplier antara lain. Tabel Pesanan memiliki referensi kunci asing ke Pelanggan, Alamat dan Tenaga Penjual antara lain. Semua tabel dalam rantai ini memiliki banyak kolom yang didefinisikan sebagai NOT NULL dan/atau dibatasi oleh CHECK dan batasan lainnya. Beberapa tabel ini sendiri memiliki lebih banyak kunci asing.

Sekarang bayangkan Anda ingin menulis prosedur tersimpan (OrderDetailStatusUpdate) yang tugasnya memperbarui status pesanan untuk satu baris pada tabel OrderDetail. Ini memiliki tiga parameter input @OrderId, @ProductId dan @OrderStatusId. Pikirkan tentang apa yang perlu Anda lakukan untuk menyiapkan tes untuk prosedur ini. Anda perlu menambahkan setidaknya dua baris ke tabel OrderDetail termasuk semua kolom NOT NULL. Anda juga perlu menambahkan catatan induk ke semua tabel yang direferensikan FK, dan juga ke tabel mana pun di atasnya dalam hierarki, memastikan bahwa semua sisipan Anda mematuhi semua nullability dan batasan lain pada tabel tersebut juga. Menurut hitungan saya, setidaknya ada 11 tabel yang perlu diisi, semuanya untuk satu tes sederhana. Dan bahkan jika Anda menggigit peluru dan melakukan semua pengaturan itu, di beberapa titik di masa depan seseorang mungkin (mungkin akan) datang dan menambahkan kolom NOT NULL baru ke salah satu tabel itu atau mengubah batasan yang akan menyebabkan pengujian Anda gagal - dan kegagalan itu sebenarnya tidak ada hubungannya dengan pengujian Anda atau prosedur tersimpan yang Anda uji. Salah satu prinsip dasar pengembangan yang digerakkan oleh tes adalah bahwa tes seharusnya hanya memiliki alasan untuk gagal, saya hitung lusinan.

TSQLT.FakeTable untuk menyelamatkan.

Apa minimum yang sebenarnya perlu Anda lakukan untuk menyiapkan tes untuk prosedur itu? Anda memerlukan dua baris ke tabel OrderDetail (satu yang diperbarui, satu yang tidak) dan satu-satunya kolom yang "perlu" Anda pertimbangkan adalah OrderId dan ProductId (kunci pengenal) ditambah OrderStatusId - kolom yang sedang diperbarui. Kolom lainnya meskipun penting dalam keseluruhan desain, tidak memiliki relevansi dengan objek yang diuji. Dalam pengujian Anda untuk OrderDetailStatusUpdate, Anda akan mengikuti langkah-langkah berikut:

  • Panggil tSQLt.FakeTable 'dbo.OrderDetail'
  • Buat tabel #expected (dengan kolom OrderId, ProductId, dan OrderStatusId) dan isi dengan dua baris yang Anda harapkan akan berakhir (satu akan memiliki OrderStatusId yang diharapkan, yang lain bisa NULL)
  • Tambahkan dua baris ke tabel OrderDetail yang sekarang diejek (hanya OrderId dan ProductId)
  • Panggil prosedur yang sedang diuji OrderDetailStatusUpdate dengan meneruskan OrderID dan ProductID untuk salah satu baris yang disisipkan ditambah OrderStatusId yang Anda ubah.
  • Gunakan tSQLt.AssertEqualsTable untuk membandingkan tabel #expected dengan tabel OrderDetail. Pernyataan ini hanya akan membandingkan kolom pada tabel #expected, kolom lain di OrderDetail akan diabaikan

Membuat tes ini sangat cepat dan satu-satunya alasan kemungkinan gagal adalah karena sesuatu yang berkaitan dengan kode yang diuji telah berubah dalam skema yang mendasarinya. Perubahan pada kolom lain pada tabel OrderDetail atau tabel induk/grand-parent tidak akan menyebabkan pengujian ini rusak.

Jadi alasan untuk menggunakan tSQLt.FakeTable (atau jenis objek tiruan lainnya) adalah untuk menyediakan isolasi pengujian yang sangat kuat dan hanya menguji persiapan data.

4
datacentricity 24 April 2020, 17:45