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

时间:2012-11-30 10:01:40

标签: javascript jasmine

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

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

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

4 个答案:

答案 0 :(得分:98)

您必须链接method1method2作为EricG评论,而不是andCallThrough()(或版本2.0中的and.callThrough())。它将委托给真正的实现

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

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

然后你可以验证:

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

答案 1 :(得分:16)

如果您使用的是Typescript,将方法强制转换为public class Map { Scanner scanner; int mapHeight = 5, mapWidth = 7; String[] map = new String[mapHeight]; BufferedImage ground, wall; public Map(){ loadMap(); loadGround(); loadWall(); } private void loadMap() { try{ scanner = new Scanner(new FileInputStream("/home/bobalice/Map.txt")); for(int i = 0; i < mapHeight; i++) { map[i] = scanner.nextLine(); } }catch(IOException e){ System.err.println("Error: Map file doesn't exist!"); }finally{ if(scanner != null) scanner.close(); } } private void loadGround() { try{ ground = ImageIO.read(new File("/home/bobalice/ground.png")); }catch(IOException e){ System.err.println("Error: ground.png doesn't exist!"); } } /// private void loadWall() { try{ wall = ImageIO.read(new File("/home/bobalice/wall.png")); }catch(IOException e){ System.err.println("Error: wall.png doesn't exist!"); } } public String[] getMap() { return map; } public BufferedImage getGround() { return ground; } public BufferedImage getWall() { return wall; } 会很有帮助。在上面的答案中(奇怪的是我没有代表发表评论):

Jasmine.Spy

我不知道我是否过度工程,因为我缺乏知识......

对于Typescript,我想要:

  • 来自基础类型的智能感知
  • 仅模拟函数中使用的方法的能力

我发现这很有用:

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

答案 2 :(得分:3)

角度9

在测试注入简单服务的组件时,使用jasmine.createSpyObj是理想的选择。例如:假设在我的HomeComponent中有一个HomeService(注入)。 HomeService中的唯一方法是getAddress()。 创建HomeComponent测试套件时,我可以将组件和服务初始化为:

describe('Home Component', () => {
    let component: HomeComponent;
    let fixture: ComponentFixture<HomeComponent>;
    let element: DebugElement;
    let homeServiceSpy: any;
    let homeService: any;

    beforeEach(async(() => {
        homeServiceSpy = jasmine.createSpyObj('HomeService', ['getAddress']);

        TestBed.configureTestingModule({
           declarations: [HomeComponent],
           providers: [{ provide: HomeService, useValue: homeServiceSpy }]
        })
        .compileComponents()
        .then(() => {
            fixture = TestBed.createComponent(HomeComponent);
            component = fixture.componentInstance;
            element = fixture.debugElement;
            homeService = TestBed.get(HomeService);
            fixture.detectChanges();
        });
    }));

    it('should be created', () => {
        expect(component).toBeTruthy();
    });

    it("should display home address", () => { 
        homeService.getAddress.and.returnValue(of('1221 Hub Street'));
        fixture.detectChanges();

        const address = element.queryAll(By.css(".address"));

        expect(address[0].nativeNode.innerText).toEqual('1221 Hub Street');
    });
 });

这是使用jasmine.createSpyObj测试组件的简单方法。但是,如果您的服务具有更多方法和更复杂的逻辑,则建议您创建一个模拟服务而不是createSpyObj。例如: providers: [{ provide: HomeService, useValue: MockHomeService }]

希望这会有所帮助!

答案 3 :(得分:0)

在@Eric Swanson的答案的基础上,我创建了一个更好的可读性并记录在案的函数,供在测试中使用。我还通过将参数作为函数键入来添加一些类型安全性。

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

/**
 * 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;
}

用法如下:

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

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