Làm thế nào để khai một phương pháp của đối tượng mô phỏng hoa nhài?


76

Theo tài liệu của Jasmine, một mô hình có thể được tạo ra như thế này:

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

Làm thế nào để bạn khai một trong những phương pháp này? Ví dụ, nếu bạn muốn kiểm tra điều gì xảy ra khi một phương thức ném một ngoại lệ, bạn sẽ làm điều đó như thế nào?


3
Bạn có thể cố gắng chuỗi nó với andCallThrough. Nó không được ghi lại rõ ràng: /
EricG

Câu trả lời:


117

Bạn phải xâu chuỗi method1, method2như EricG đã nhận xét, nhưng không phải với andCallThrough()(hoặc and.callThrough()trong phiên bản 2.0). Nó sẽ ủy quyền cho việc triển khai thực tế .

Trong trường hợp này, bạn cần xâu chuỗi and.callFake()và chuyển hàm bạn muốn được gọi (có thể ném ngoại lệ hoặc bất cứ điều gì bạn muốn):

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

Và sau đó bạn có thể xác minh:

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

7
Jasmine 2.0 đã thay đổi cú pháp để .and.callFake(), .and.callThrough(), .and.returnValue() jasmine.github.io/2.0/introduction.html#section-Spies
alxndr

20

Nếu bạn đang sử dụng Typecript, sẽ hữu ích khi ép kiểu Jasmine.Spy. Trong Câu trả lời ở trên (kỳ lạ là tôi không có đại diện bình luận):

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

Tôi không biết liệu mình có đang làm quá kỹ thuật hay không, vì tôi thiếu kiến ​​thức ...

Đối với bản ghi, tôi muốn:

  • Intellisense từ loại cơ bản
  • Khả năng chỉ bắt chước các phương thức được sử dụng trong một hàm

Tôi thấy điều này hữu ích:

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']
        ]);
    });
});

Câu trả lời được chấp nhận không biên dịch cho tôi (jasmine 2,5) nhưng giải pháp này đã hoạt động!
Peter Morris,

Cải tiến nhỏ - todoService: {[key: string]: jasmine.Spy} = jasmine.createSpyObj(...); todoService.anyMethod.and....- không cần truyền sang Spy mọi lúc.
Kai

Cảm ơn @Kai, tôi đã thêm một số chi tiết. Tôi cần (muốn?) Nhận dạng kiểu làm kiểu chính hơn là một đối tượng gián điệp động. Cá nhân tôi muốn đối tượng hoạt động và cảm thấy giống như đối tượng thật và sau đó chỉ chuyển sang Spy khi tôi đang thử nghiệm.
Eric Swanson

3

Góc 9

Sử dụng jasmine.createSpyObjlà lý tưởng khi kiểm tra một thành phần trong đó một dịch vụ đơn giản được đưa vào. Ví dụ: giả sử, trong HomeComponent của tôi, tôi có HomeService (được tiêm vào). Phương thức duy nhất trong HomeService là getAddress (). Khi tạo bộ thử nghiệm HomeComponent, tôi có thể khởi tạo thành phần và dịch vụ dưới dạng:

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');
    });
 });

Đây là một cách đơn giản để kiểm tra thành phần của bạn bằng cách sử dụng jasmine.createSpyObj. Tuy nhiên, nếu dịch vụ của bạn có nhiều phương thức logic phức tạp hơn, tôi khuyên bạn nên tạo một mockService thay vì createSpyObj. Ví dụ: providers: [{ provide: HomeService, useValue: MockHomeService }]

Hi vọng điêu nay co ich!


0

Dựa trên câu trả lời của @Eric Swanson, tôi đã tạo ra một chức năng có thể đọc và ghi lại tốt hơn để sử dụng trong các thử nghiệm của mình. Tôi cũng đã thêm một số loại an toàn bằng cách nhập tham số dưới dạng một hàm.

Tôi khuyên bạn nên đặt mã này ở đâu đó trong lớp kiểm tra chung, để bạn có thể nhập mã này vào mọi tệp kiểm tra cần nó.

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

Cách sử dụng sẽ như sau:

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

const translator: TranslateService = jasmine.createSpyObj('TranslateService', ['getDefaultLang']);
asSpy(translator.getDefaultLang).and.returnValue(null);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.