تحديث ، يونيو 2023 : لم يعد هذا الريبو والأداة يتم الحفاظ عليهما. يرجى الاطلاع على go.uber.org/mock للحصول على شوكة محفوظة بدلاً من ذلك.
Gomock هو إطار سخرية للغة البرمجة GO. يتكامل بشكل جيد مع حزمة testing
المدمجة في GO ، ولكن يمكن استخدامها في سياقات أخرى أيضًا.
بمجرد تثبيت GO ، قم بتثبيت أداة mockgen
.
ملاحظة : إذا لم تكن قد فعلت ذلك ، فتأكد بالفعل من إضافة $GOPATH/bin
إلى PATH
.
للحصول على أحدث إصدار تم إصداره:
GO111MODULE=on go get github.com/golang/mock/[email protected]
go install github.com/golang/mock/[email protected]
إذا كنت تستخدم mockgen
في خط أنابيب CI الخاص بك ، فقد يكون من الأنسب التثبيت في إصدار Mockgen معين. يجب أن تحاول الاحتفاظ بالمكتبة متزامنة مع إصدار Mockgen المستخدم لإنشاء Mocks الخاص بك.
لدى mockgen
وضعين للتشغيل: المصدر والانعكاس.
يولد وضع المصدر واجهات وهمية من ملف مصدر. يتم تمكينه باستخدام علم -Source. أعلام أخرى قد تكون مفيدة في هذا الوضع هي -imports و -aux_files.
مثال:
mockgen -source=foo.go [other options]
ينشئ MODENT MODER واجهات وهمية عن طريق إنشاء برنامج يستخدم الانعكاس لفهم الواجهات. يتم تمكينه عن طريق تمرير وسيطتين غير متنازلتين: مسار استيراد ، وقائمة مفصولة بالفاصلة من الرموز.
يمكنك استخدام "." للإشارة إلى حزمة المسار الحالي.
مثال:
mockgen database/sql/driver Conn,Driver
# Convenient for `go:generate`.
mockgen . Conn,Driver
يتم استخدام أمر mockgen
لإنشاء رمز المصدر لفئة وهمية بالنظر إلى ملف مصدر GO الذي يحتوي على واجهات للسخرية. وهو يدعم الأعلام التالية:
-source
: ملف يحتوي على واجهات يسخر منها.
-destination
: ملف لكتابة رمز المصدر الناتج. إذا لم تقم بتعيين هذا ، فسيتم طباعة الرمز إلى الإخراج القياسي.
-package
: الحزمة لاستخدامها في رمز مصدر الفئة الناتجة الناتجة. إذا لم تقم بتعيين هذا ، فسيتم mock_
اسم الحزمة مع حزمة ملف الإدخال.
-imports
: قائمة بالواردات الصريحة التي يجب استخدامها في الكود المصدر الناتج ، المحددة كقائمة مفصولة بفاصلة من عناصر النموذج foo=bar/baz
، حيث يكون bar/baz
هو الحزمة التي يتم استيرادها و foo
هي المعرف هي المعرف لاستخدام الحزمة في رمز المصدر الذي تم إنشاؤه.
-aux_files
: قائمة بالملفات الإضافية التي يجب استشارةها لحل الواجهات المدمجة على سبيل المثال المحددة في ملف مختلف. يتم تحديد ذلك كقائمة مفصولة مفصولة لعناصر النموذج foo=bar/baz.go
، حيث يكون bar/baz.go
هو الملف المصدر و foo
هو اسم حزمة هذا الملف المستخدم بواسطة ملف -source.
-build_flags
: (عكس الوضع فقط) مرر العلامات حرفيًا go build
.
-mock_names
: قائمة بالأسماء المخصصة للنهايات التي تم إنشاؤها. يتم تحديد ذلك كقائمة مفصولة مفصولة لعناصر مستودع Repository=MockSensorRepository,Endpoint=MockSensorEndpoint
، MockSensorRepository
سيتم تسمية Repository
اسم الواجهة وسيتم تسمية اسم الواجهة على بعد). إذا لم يكن لدى أحد الواجهات اسم مخصص محدد ، فسيتم استخدام اتفاقية التسمية الافتراضية.
-self_package
: مسار استيراد الحزمة الكامل للرمز الذي تم إنشاؤه. الغرض من هذا العلم هو منع دورات الاستيراد في الكود الذي تم إنشاؤه من خلال محاولة تضمين الحزمة الخاصة به. يمكن أن يحدث هذا إذا تم تعيين حزمة Mock على أحد مدخلاتها (عادةً ما تكون الرئيسية) والإخراج هو stdio حتى لا يتمكن Mockgen من اكتشاف حزمة الإخراج النهائية. سيخبر تعيين هذه العلامة Mockgen التي تستبعدها.
-copyright_file
: ملف حقوق الطبع والنشر المستخدم لإضافة رأس حقوق الطبع والنشر إلى رمز المصدر الناتج.
-debug_parser
: طباعة نتائج المحلل فقط.
-exec_only
: (عكس الوضع) إذا تم تعيينه ، قم بتنفيذ برنامج الانعكاس هذا.
-prog_only
: (الوضع العاكس) قم بإنشاء برنامج الانعكاس فقط ؛ اكتبها إلى stdout والخروج.
-write_package_comment
: يكتب حزمة التعليق الوثائق (GODOC) إذا كان صحيحًا. (صواب افتراضي)
للحصول على مثال على استخدام mockgen
، انظر sample/
الدليل. في الحالات البسيطة ، ستحتاج فقط إلى علم -source
.
type Foo interface {
Bar ( x int ) int
}
func SUT ( f Foo ) {
// ...
}
func TestFoo ( t * testing. T ) {
ctrl := gomock . NewController ( t )
// Assert that Bar() is invoked.
defer ctrl . Finish ()
m := NewMockFoo ( ctrl )
// Asserts that the first and only call to Bar() is passed 99.
// Anything else will fail.
m .
EXPECT ().
Bar ( gomock . Eq ( 99 )).
Return ( 101 )
SUT ( m )
}
إذا كنت تستخدم إصدار GO من 1.14+ ، فإن إصدار Mockgen من 1.5.0+ ، وتمرر *testing.t إلى gomock.NewController(t)
لم تعد بحاجة إلى استدعاء ctrl.Finish()
بشكل صريح. سيتم استدعاؤه لك تلقائيًا من وظيفة التنظيف المسجلة ذاتيا.
type Foo interface {
Bar ( x int ) int
}
func SUT ( f Foo ) {
// ...
}
func TestFoo ( t * testing. T ) {
ctrl := gomock . NewController ( t )
defer ctrl . Finish ()
m := NewMockFoo ( ctrl )
// Does not make any assertions. Executes the anonymous functions and returns
// its result when Bar is invoked with 99.
m .
EXPECT ().
Bar ( gomock . Eq ( 99 )).
DoAndReturn ( func ( _ int ) int {
time . Sleep ( 1 * time . Second )
return 101
}).
AnyTimes ()
// Does not make any assertions. Returns 103 when Bar is invoked with 101.
m .
EXPECT ().
Bar ( gomock . Eq ( 101 )).
Return ( 103 ).
AnyTimes ()
SUT ( m )
}
عندما يبلغ أحد المطابقات عن فشل ، فإنه يطبع القيمة المستلمة ( Got
) مقابل القيمة المتوقعة ( Want
).
Got: [3]
Want: is equal to 2
Expected call at user_test.go:33 doesn ' t match the argument at index 1.
Got: [0 1 1 2 3]
Want: is equal to 1
Want
تأتي قيمة Want
من طريقة String()
. إذا كان الإخراج الافتراضي للمطابقة لا يلبي احتياجاتك ، فيمكن تعديله على النحو التالي:
gomock . WantFormatter (
gomock . StringerFunc ( func () string { return "is equal to fifteen" }),
gomock . Eq ( 15 ),
)
هذا يعدل إخراج Matcher gomock.Eq(15)
من أجل Want:
من is equal to 15
is equal to fifteen
.
Got
تأتي قيمة Got
من طريقة String()
إذا كانت متوفرة. في بعض الحالات ، يصعب قراءة إخراج كائن ما (على سبيل المثال ، []byte
) وسيكون من المفيد للاختبار طباعته بشكل مختلف. فيما يلي يعدل كيفية تنسيق قيمة Got
:
gomock . GotFormatterAdapter (
gomock . GotFormatterFunc ( func ( i interface {}) string {
// Leading 0s
return fmt . Sprintf ( "%02d" , i )
}),
gomock . Eq ( 15 ),
)
إذا كانت القيمة المستلمة 3
، فسيتم طباعتها على أنها 03
.
cannot find package "."
... github.com/golang/mock/mockgen/model
إذا صادفت هذا الخطأ أثناء استخدام وضع الانعكاس وفن تبعيات ، فهناك ثلاثة حلول يمكنك الاختيار من بينها:
import _ "github.com/golang/mock/mockgen/model"
.--build_flags=--mod=mod
إلى أمر mockgen الخاص بك. يرجع هذا الخطأ إلى تغييرات في السلوك الافتراضي لأمر go
في الإصدارات الأكثر حداثة. يمكن العثور على مزيد من التفاصيل في #494.