Skip to content
Advertisement

Jest equivalent to RSpec lazy evaluated variables (let)?

In rspec you can do something like this:

let(:input) { 'foo' }
before_each do
   setup_some_thing(input)
end

context 'when input is bar do
  let(:input) { 'bar' }
  it 'does something different' do
  end
end

context 'when input is baz do
  let(:input) { 'baz' }
  it 'does something else different' do
  end
end

This allows you to define a method call or instantiation of a large object as a sum of its smaller parts. You can then override those individual small parts inside different contexts. The idea being that you create a happy path before each test, and then specify deviations from the happy path within your context blocks.

Unfortunately, I can’t seem to do this with Jest. I’ve tried the following:

beforeEach(() => {
  let input = 'foo';
  beforeEach(() => {
    setupSomeThing(input);
  });

  describe('when input is bar', () => {
    input = 'bar';
    it('does something different', () => {

    });
  });

  describe('when input is baz', () => {
    input = 'baz';
    it('does something different', () => {

    });
  });
});

Because jest executes every describe block before running any specific describe block, input is always ‘baz’. Does anyone know a work around, or a way to get the rspec behavior?

Thanks in advance!

Update

You can get similar behavior (albeit without lazy evaluation) using beforeAll.

beforeEach(() => {
  let input = 'foo';
  beforeEach(() => {
    setupSomeThing(input);
  });

  describe('when input is bar', () => {
    beforeAll(() => {
     input = 'bar';
    });

    it('does something different', () => {

    });
  });

  describe('when input is baz', () => {
    beforeAll(() => {
     input = 'baz';
    });        

    it('does something different', () => {

    });
  });
});

Advertisement

Answer

The best solutions I’ve found have been libraries like

https://github.com/stalniy/bdd-lazy-var

and

https://github.com/tatyshev/given2

If you don’t want to introduce a dependency, you can get similar behavior (albeit without lazy evaluation) by doing something like this:

beforeEach(() => {
  let input = 'foo';
  beforeEach(() => {
    setupSomeThing(input);
  });

  describe('when input is bar', () => {
    beforeAll(() => {
     input = 'bar';
    });

    it('does something different', () => {

    });
  });

  describe('when input is baz', () => {
    beforeAll(() => {
     input = 'baz';
    });        

    it('does something different', () => {

    });
  });
});
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement