Jasmine .toHaveBeenCalled什么时候匹配参数?

时间:2018-02-04 10:29:31

标签: angular typescript jasmine karma-jasmine angular-test

我有以下角度服务及其茉莉花测试。测试调用f1()和间谍f2()。函数f2采用变量v2并对其进行修改(将字段a设置为3)。应该使用v2调用函数f2(如f1中所声明的那样),但是我的测试在 toHaveBeenCalledWith 上失败,并且表示在f2函数调用之后实际调用了对象。在函数调用之后,jasmine是否与.toHaveBeenCalledWith的参数匹配,这不应该是推荐的方法,或者我在这里犯了一些错误。

服务

export class JasmineTestClass{
    constructor(){
    }
    f2(v2){
        v2.a = 3
    };
    f1(v1){
        let v2 = {
            a:30
        };
        this.f2(v2);
    }
}

测试

describe('Test', () => {
    let service: JasmineTestClass;
    beforeEach(() => {
        service = new JasmineTestClass();
        spyOn(service, 'f2').and.callThrough();
    });
    let v1 = {
        a:2, b:3
    };
    let v2 = {
        a:30
    };
    it('should succeed', () => {
        service.f1(v1);
        expect(service.f2).toHaveBeenCalledWith(v2);    //this is failing
    });
})

日志:

Test should succeed FAILED

Expected spy f2 to have been called with [Object ({a:30})] but actual calls were [Object ({a:3})]

请注意我在测试时在Chrome中进行了调试,并且使用v2 = {a:30}调用函数f2()。

1 个答案:

答案 0 :(得分:0)

toHaveBeenCalledWith在断言时匹配调用参数。

Jasmine间谍只是在内部保存参数引用。可以通过记录service.f2.calls.all()对象来跟踪调用参数。

这里的问题是f2修改了通过引用传递的对象。在v2来电之后的任何地方都不存在v2.a === 30 f2原始版本。

此类案例的正确策略是创建细粒度测试,每个单元一次测试(方法)。 callThrough使用的事实表明单位彼此之间没有隔离,默认情况下只使用spyOn(service, 'f2')存根是个好主意:

it('should succeed', () => {
  service.f1(v1);
  expect(service.f2).toHaveBeenCalledWith({ a:30 });
});

it('should succeed', () => {
  const obj = { a:30 };
  service.f2(obj);
  expect(obj).toEqual({ a:3 });
});

现在我们正在测试这两种方法到底发生了什么。