Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to mock getter #29

Closed
lebeier opened this issue Apr 26, 2020 · 2 comments
Closed

Unable to mock getter #29

lebeier opened this issue Apr 26, 2020 · 2 comments

Comments

@lebeier
Copy link

lebeier commented Apr 26, 2020

Is it possible to mock getters?
I always get the error Cannot assign to 'xyz' because it is a read-only property

@wihd
Copy link

wihd commented Aug 17, 2020

Although it would be better to integrate support for getters into the library, it is possible to mock a getter whilst using jest-mock-extended. Suppose you have an interface like this.

interface Strings {
    readonly size: number;
    item(index: number): string;
}

Just creating a mock for this interface using mock<Strings> will allow you to mock the item method. But since the type of size is not a function, an expression like mockObject.size.mockReturnValue(3) is a type error since you cannot call a method on an integer value.

However it is possible to define a property that uses a getter function directly on the implementation object that jest-mock-extended uses to record the state for its mock object. We need to pass an empty object into the mock<>() function so that we get a reference to this object. Consider the following code:

    // Construct the mockers
    const baseMock = {};
    const mockStrings = mock<Strings>(baseMock);
    const mockSizeGetter = jest.fn<number, []>();
    Object.defineProperty(baseMock, 'size', { get: mockSizeGetter });

This code creates an object mockStrings that mocks the Strings interface. The jest mock function mockSizeGetter is set to be the getter function for the size property. You have to call defineProperty on the baseMock object after creating the mocker. Otherwise the mock<>() function will attempt to alter it, which does not work since there is no setter function.

Now we can prepare the mockers to pretend to be a collection of three strings.

    mockSizeGetter.mockReturnValue(3);
    mockStrings.item
        .mockReturnValueOnce('zero')
        .mockReturnValueOnce('one')
        .mockReturnValueOnce('two');

The following code demonstrates that the getter have been mocked.

    const concatenate = (strings: Strings): string => {
        let result = '';
        for (let i = 0; i < strings.size; ++i) {
            if (i > 0) {
                result += ',';
            }
            result += strings.item(i);
        }
        return result;
    }

    expect(concatenate(mockStrings)).toEqual('zero,one,two');

@lebeier
Copy link
Author

lebeier commented Aug 28, 2020

Thanks for this example. While I am not working with any projects that are using jest framework at the moment, I will give it a try in the future. =)

@lebeier lebeier closed this as completed Aug 28, 2020
Beraliv pushed a commit to Beraliv/jest-mock-extended that referenced this issue May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants