使用 Jasmine 进行 Angular 单元测试:如何删除或修改 spyOn

Posted

技术标签:

【中文标题】使用 Jasmine 进行 Angular 单元测试:如何删除或修改 spyOn【英文标题】:Angular unit testing with Jasmine: how to remove or modify spyOn 【发布时间】:2015-05-03 11:55:14 【问题描述】:

AngularJS v1.2.26

茉莉花v2.2.0

如何更改或删除spyOn 的行为?当我尝试覆盖它时,我收到以下错误:Error: getUpdate has already been spied upon

var data1 = 'foo';
var data2 = 'bar';

describe("a spec with a spy", function()

    beforeEach(module('app'));

    var $q;

    beforeEach(inject(function(_updateService_, _$q_)
        updateService = _updateService_;

        //spy the results of the getUpdate()
        $q = _$q_;
        var deferred = $q.defer();
        deferred.resolve( data1 );
        spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);

    ));

    describe('and here the spy should be different', function() 

        it('returns a different value', function() 

          var deferred = $q.defer();
          deferred.resolve( data2 );
          spyOn(updateService, 'getUpdate'); //ERROR HERE
          updateService.getUpdate.and.returnValue(deferred.promise);

          ...

        );
    );

...

当我删除第二个 spyOn 时,测试不起作用。

我该怎么做?

【问题讨论】:

Jasmine SpyOn same method more than once的可能重复 【参考方案1】:

你可以覆盖它

updateService.getUpdate = jasmine.createSpy().and.returnValue(etc)

【讨论】:

有没有办法完全删除间谍?回到原来的功能? 最大的问题是,如果您在每个测试中都没有相同的功能,那为什么还要设置全局间谍呢?如果要为每个测试设置 spy,则为每个测试设置 spy。 @Jan 如果我有 50 个测试,并且其中只有一个具有与其他功能不同的功能的间谍,我宁愿只在那里更改一次,而不是每次测试. 好吧,就我而言,它位于全局对象(由本机代码定义)上。所以我有多个规范需要在不同的情况下返回不同的值...... 会不会通过调用 jasmine.createSpy().and.callThrought() 回到原来的实现?【参考方案2】:

你可以覆盖间谍的返回值

    var deferred = $q.defer();
    deferred.resolve( data1 );

    var getUpdateSpy = spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);



    var newDeferred = $q.defer();
    newDeferred.resolve( data2 );

    getUpdateSpy.and.returnValue(newDeferred.promise);        

【讨论】:

工作于 18/6/2019 如果您的所有代码都在同一个描述中,这可能会起作用,但否则不会因为未定义 getUpdateSpy... @GarfieldKlon 您可以通过在父 describe 块中定义变量 getUpdateSpy 来解决此问题。【参考方案3】:

从 jasmine v2.5 开始,使用全局 allowRespy() 设置。

jasmine.getEnv().allowRespy(true);

当您不想和/或无法接触到第一个间谍时,您可以多次致电spyOn()。注意它会返回之前的间谍(如果有的话)。

spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);
...
spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);

【讨论】:

老实说,这是我多年来一直在寻找的答案。我希望它在互联网上更流行。一百万谢谢:)【参考方案4】:

更简单的方法:

updateService.getUpdate.and.returnValue(Observable.of(status:true));

它会返回值。

【讨论】:

谢谢。其他人都错过了明显的答案。 您的类型系统似乎没有抱怨。这就引出了一个问题:为什么要使用 Typescript?【参考方案5】:

另一种选择:

(yourService.method as jasmine.Spy).and.returnValue(value);

【讨论】:

【参考方案6】:

绿色复选标记的答案对我不起作用,但确实如此:

yourCoolService.createThing = jasmine.createSpy('notreal', function()).and.returnValue();

您的 jasmine 测试将运行,但是当您启动应用程序时,如果您不将随机字符串和空函数作为 args 放入 createSpy(),您的应用程序打字稿会大声对您大喊大叫。

【讨论】:

这可能是由于更新了 Jasmine 版本。我正在使用 2.7,这对我有用。

以上是关于使用 Jasmine 进行 Angular 单元测试:如何删除或修改 spyOn的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jasmine 进行 Angular 单元测试:如何删除或修改 spyOn

使用 jasmine / karma 进行 Angular 4 单元测试和 http post mocking - 如何修复

使用 Karma Jasmine 的 Angular 1.5 组件模板单元测试

使用jasmine来对js进行单元测试

如何使用 Jasmine 为私有方法编写 Angular / TypeScript 单元测试

使用 jasmine 和 karma 进行单元测试时形成数组错误