我试图覆盖(猴子补丁)Jasmine框架的it()
函数,在这个过程中,我想知道一个函数是否作为第二个参数传递给it()
函数是async
类型。我尝试使用instanceof Promise
,因为所有async
函数都返回一个promise,但它永远不会解析为true,它永远不会进入下面代码块中的if块。我已经尝试将所有函数记录到控制台,我发现所有async()
函数规范的返回类型都为tslib_1.awaiter(some args..)
。
这就是我所拥有的:
let newIt = jasmine.getEnv().it;
jasmine.getEnv().it = function(...args): jasmine.Spec {
// do something.
if(args[1] instanceOf Promise) {
debugger; // never comes in here.
// catch error.
}
return newIt.apply(this, arguments);
}
我在这里做错了什么?有人可以指出我正确的方向吗?
谢谢。
编辑:我们说我有以下两个虚拟规格,一个是异步,另一个是同步:
异步测试:
const exp = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 500);
});
};
it('asyncTest', async () => {
expect(await exp()).toEqual(1);
}, 600);
同步:
it('testNon', () => {
expect(true).toBe(true);
});
答案 0 :(得分:1)
这是XY问题。正如this answer中所指出的,通常无需检查它是async
函数,因为这无关紧要。 async
函数只是一个返回promise的函数。 () => Promise.resolve()
和async () => {}
都应该以同样的方式对待。
事实证明,在转换的TypeScript代码中无法区分async
和常规函数 - 这两者都只是常规函数。
args[1] instanceOf Promise
不正确,因为函数不是Promise
的实例。
猴子修补通常以这种方式执行(这不是特定于Jasmine或这种情况):
let newIt = jasmine.getEnv().it;
jasmine.getEnv().it = function(...args): jasmine.Spec {
const fn = args[1];
let newFn;
if (fn.length > 0) {
// async spec with done param
newFn = function (done) {
const result = fn.call(this, done);
if(result instanceOf Promise)
// or even better,
// if(result && typeof result.then === 'function')
debugger;
return result;
}
} else {
newFn = function () {
const result = fn.call(this);
if(result instanceOf Promise)
debugger;
return result;
}
}
args[1] = newFn;
return newIt.apply(this, args);;
}
它的测试函数结果应该被检查为Promise
的实例(或者如果它是可以检查的话)。
答案 1 :(得分:0)
这不起作用,因为异步函数总是返回一个承诺,但它们本身并不承诺。
简单的答案是查看相关函数的构造函数(但我将解释为什么你不应该在之后):
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!--<view class="us.sam.views.ButtonBar$LabeledButton$Button"-->
<ImageView
android:id="@+id/ButtonBar_LabeledButton_ButtonImageView"
style="@style/ButtonBar_LabeledButton_ButtonImageView"/>
<!--android:src="@drawable/v__ic_add_circle_outline_black_24dp"-->
<!--view class="us.sam.views.ButtonBar$LabeledButton$Label"-->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ButtonBar_LabeledButton_LabelTextView"
style="@style/ButtonBar_LabeledButton_LabelTextView"/>
<!--android:text="Add New"-->
</merge>
这种方法的问题在于,异步函数实际上并不能与返回promise的常规函数区分开来。最好使用public class LabeledButton : LinearLayout
{
private ImageView _buttonIV;
private TextView _labelTV;
private int _buttonIV_src;
private string _labelTV_text;
public LabeledButton(Context context, IAttributeSet attributes) : base(context, attributes)
{
ReadAttributes(context, attributes);
}
private void ReadAttributes(Context context, IAttributeSet attributes)
{
Android.Content.Res.TypedArray typedArray = context.ObtainStyledAttributes(attributes, Resource.Styleable.LabeledButton);
_buttonIV_src = typedArray.GetResourceId(Resource.Styleable.LabeledButton_button_imageview_src, 0);
_labelTV_text = typedArray.GetString(Resource.Styleable.LabeledButton_label_textview_text);
typedArray.Recycle();
}
protected override void OnFinishInflate()
{
base.OnFinishInflate();
_buttonIV = FindViewById<ImageView>(Resource.Id.ButtonBar_LabeledButton_ButtonImageView);
_labelTV = FindViewById<TextView>(Resource.Id.ButtonBar_LabeledButton_LabelTextView);
_buttonIV.SetImageResource(_buttonIV_src);
_labelTV.Text = _labelTV_text;
}
}
将任何函数调用的结果转换为const isAsync = func.constructor.name === 'AsyncFunction';
和Promise.resolve
。