Javascript 如何存根茉莉花模拟对象的方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13642884/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 12:34:12  来源:igfitidea点击:

How to stub a method of jasmine mock object?

javascriptjasmine

提问by Adelin

According to the Jasmine documentation, a mock can be created like this:

根据 Jasmine 文档,可以像这样创建一个模拟:

jasmine.createSpyObj(someObject, ['method1', 'method2', ... ]);

How do you stub one of these methods? For example, if you want to test what happens when a method throws an exception, how would you do that?

你如何存根这些方法之一?例如,如果你想测试当一个方法抛出异常时会发生什么,你会怎么做?

回答by zbynour

You have to chain method1, method2as EricG commented, but not with andCallThrough()(or and.callThrough()in version 2.0). It will delegate to real implementation.

正如 EricG 评论的那样,您必须链接method1method2但不能使用andCallThrough()(或and.callThrough()在 2.0 版中)。它将委托给真正的实施

In this case you need to chain with and.callFake()and pass the function you want to be called (can throw exception or whatever you want):

在这种情况下,您需要链接and.callFake()并传递您想要调用的函数(可以抛出异常或任何您想要的):

var someObject = jasmine.createSpyObj('someObject', [ 'method1', 'method2' ]);
someObject.method1.and.callFake(function() {
    throw 'an-exception';
});

And then you can verify:

然后你可以验证:

expect(yourFncCallingMethod1).toThrow('an-exception');

回答by Eric Swanson

If you are using Typescript, it's helpful to cast the method as Jasmine.Spy. In the above Answer (oddly I don't have rep for comment):

如果您使用的是 Typescript,将方法转换为Jasmine.Spy. 在上面的答案中(奇怪的是我没有代表发表评论):

(someObject.method1 as Jasmine.Spy).and.callFake(function() {
  throw 'an-exception';
});

I don't know if I'm over-engineering, because I lack the knowledge...

我不知道我是否过度设计,因为我缺乏知识......

For Typescript, I want:

对于打字稿,我想要:

  • Intellisense from the underlying type
  • The ability to mock just the methods used in a function
  • 来自底层类型的智能感知
  • 仅模拟函数中使用的方法的能力

I've found this useful:

我发现这很有用:

namespace Services {
    class LogService {
        info(message: string, ...optionalParams: any[]) {
            if (optionalParams && optionalParams.length > 0) {
                console.log(message, optionalParams);
                return;
            }

            console.log(message);
        }
    }
}

class ExampleSystemUnderTest {
    constructor(private log: Services.LogService) {
    }

    doIt() {
        this.log.info('done');
    }
}

// I export this in a common test file 
// with other utils that all tests import
const asSpy = f => <jasmine.Spy>f;

describe('SomeTest', () => {
    let log: Services.LogService;
    let sut: ExampleSystemUnderTest;

    // ARRANGE
    beforeEach(() => {
        log = jasmine.createSpyObj('log', ['info', 'error']);
        sut = new ExampleSystemUnderTest(log);
    });

    it('should do', () => {
        // ACT
        sut.doIt();

        // ASSERT
        expect(asSpy(log.error)).not.toHaveBeenCalled();
        expect(asSpy(log.info)).toHaveBeenCalledTimes(1);
        expect(asSpy(log.info).calls.allArgs()).toEqual([
            ['done']
        ]);
    });
});

回答by Mr.wiseguy

Building on @Eric Swanson's answer, I've created a better readable and documented function for using in my tests. I also added some type safety by typing the parameter as a function.

以@Eric Swanson 的回答为基础,我创建了一个更好的可读性和文档化的函数,用于在我的测试中使用。我还通过将参数作为函数键入来添加了一些类型安全性。

I would recommend to place this code somewhere in a common test class, so that you can import it in every test file that needs it.

我建议将此代码放在公共测试类中的某个位置,以便您可以将其导入到需要它的每个测试文件中。

/**
 * Transforms the given method into a jasmine spy so that jasmine functions
 * can be called on this method without Typescript throwing an error
 *
 * @example
 * `asSpy(translator.getDefaultLang).and.returnValue(null);`
 * is equal to
 * `(translator.getDefaultLang as jasmine.Spy).and.returnValue(null);`
 *
 * This function will be mostly used in combination with `jasmine.createSpyObj`, when you want
 * to add custom behavior to a by jasmine created method
 * @example
 * `const translator: TranslateService = jasmine.createSpyObj('TranslateService', ['getDefaultLang'])
 * asSpy(translator.getDefaultLang).and.returnValue(null);`
 *
 * @param {() => any} method - The method that should be types as a jasmine Spy
 * @returns {jasmine.Spy} - The newly typed method
 */
export function asSpy(method: () => any): jasmine.Spy {
  return method as jasmine.Spy;
}

Usage would be as follows:

用法如下:

import {asSpy} from "location/to/the/method";

const translator: TranslateService = jasmine.createSpyObj('TranslateService', ['getDefaultLang']);
asSpy(translator.getDefaultLang).and.returnValue(null);