【问题标题】:Error: <toHaveBeenCalled> : Expected a spy, but got Function错误:<toHaveBeenCalled>:预期是间谍,但得到了函数
【发布时间】:2018-02-20 11:03:43
【问题描述】:

这是测试代码

var list = new List([1, 2, 3, 4]);
var list2 = new List([5, 1]);

beforeAll(function () {
  spyOn(list.values, 'map').and.callThrough();

  list.map(plusOne);
});

it('Array.prototype.map()', function () {
  expect(list.values.map).not.toHaveBeenCalled();
});

This results in the following error 1) List must not call native Array function Array.prototype.map()   Message:
    Error: <toHaveBeenCalled> : Expected a spy, but got Function.
    Usage: expect(<spyObj>).toHaveBeenCalled()

  class List {
    constructor(clist = []) {
        this.values = clist;
    }
    map(f) {
        var temp = [];
        this.values.forEach((item, index) => {
                   temp.push(f(item));
                });
        this.values = temp;
        return this;
    }
}
module.exports = { List };

我不认为这是一个单元测试失败,因为无论我调用 not.tohaveBeenCalled() 还是 toHaveBeenCalled(),我都会收到相同的消息。

我正在使用节点 8.9.4 和 jasmine 2.8.0。

我相信语法是正确的,因为当我针对这些测试运行其他代码时,它们通过了。但是我的代码导致了这个错误。

我的问题是上述错误是什么意思? 问候,

【问题讨论】:

    标签: javascript jasmine


    【解决方案1】:

    我刚刚运行了以下测试,它适用于 jasmine@3.0.0

    fit('Spy on map works', () => {
            let someArray = [1, 3, 5];
            spyOn(someArray, 'map').and.callThrough();
            someArray.map(function(r){ console.log(r); });
            expect(someArray.map).toHaveBeenCalled();
     });
    

    您可能想运行此示例以了解它是否适​​用于您的测试。

    正如我在评论中所说,您的列表映射方法用新数组覆盖 list.values。因此,间谍不再存在。尝试类似:

    someArray.forEach((item, index) => {
                       someArray[index] = f(item);
    });
    

    解释发生了什么:

    //WORKS
     fit('Spy on map works', () => {
        let someArray = [1, 3, 5];
        spyOn(someArray, 'map').and.callThrough();
        someArray.forEach((item, index) => {
            someArray[index] = (item + '_t');
        });
        someArray.map(function(r){ console.log(r); });
        expect(someArray.map).toHaveBeenCalled();
    });
    //FAILS because array is another object.
    fit('Spy on map fails', () => {
        let someArray = [1, 3, 5];
        spyOn(someArray, 'map').and.callThrough();
    
        let tempArray = [];
        someArray.forEach((item, index) => {
            tempArray.push(item + '_t');
        });
        someArray = tempArray;
    
        someArray.map(function(r){ console.log(r); });
        expect(someArray.map).toHaveBeenCalled();
    });
    

    但是,您可以只监视原型。类似的东西:

     spyOn(Array.prototype, 'map').and.callThrough();
    

    然后,您的测试应该可以工作了。

    【讨论】:

    • 感谢您。我升级了茉莉花。结果相同。正如我所提到的,我确实有来自其他人的代码。因此,我的代码显然存在需要修复的问题。我不明白该错误的实际含义。我的类 List 有一个 map 方法。它包含一个值的类变量,它是一个数组。并且测试正在检查该类是否使用 List.map 而不是 array.map。我可以删除 not 并得到相同的错误这一事实表明测试没有失败,但存在错误。
    • 你能粘贴你的 List 类吗? List 类中的 map 函数是否重新实例化了 values 数组?
    • 是的,列表映射正在用新的对象数组覆盖值。因此,您的间谍不适用于这个新对象。
    • 这很奇怪。当我运行您的测试时,它可以工作。我已经更改了代码,以便复制、清空值然后执行操作,我得到相同的结果“预期间谍......”。我认为我在做一些根本错误的事情
    • 我明白你的意思。但是如果我运行另一个版本的代码,它就可以工作。如果我运行我的代码版本,则会出现错误。如果我从另一个人那里获取代码并将该方法粘贴到我的代码中,它就会失败。正常的单元测试工作。只是 spyOn 失败了。你愿意我把代码放在 GitHub 上吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多