When to use subject vs. let in RSpec

Subject allows you to define a common object to be tested in multiple examples in a single test case. It is typically used to represent an instance of the class that you are testing.

Let can be used to define any type of object, including fixtures, mocks, and helpers.

The main difference between subject and let is that subject is automatically assigned an instance of the class that you are testing, while let must be explicitly assigned a value.

Another difference is that subject is memoized, meaning that it is only evaluated once per test case. This can improve the performance of your tests, especially if you are testing complex objects.

Let is not memoized, meaning that it is evaluated every time it is called. This can be useful if you need to create a new object for each example in a test case.

Here is an example of how to use subject:

1
2
3
4
5
6
7
8
9
10
11
describe User do
  subject { User.new(name: "John Doe", email: "johndoe@example.com") }

  it "should have the correct name" do
    expect(subject.name).to eq("John Doe")
  end

  it "should have the correct email" do
    expect(subject.email).to eq("johndoe@example.com")
  end
end

In this example, the subject method is used to define a new User instance for each example in the test case.

Here is the same example but using let:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
describe User do
  let(:users) do
    [
      User.new(name: "John Doe", email: "johndoe@example.com"),
      User.new(name: "Jane Doe", email: "janedoe@example.com"),
    ]
  end

  it "should have the correct names" do
    expect(users.map(&:name)).to eq(["John Doe", "Jane Doe"])
  end

  it "should have the correct emails" do
    expect(users.map(&:email)).to eq(["johndoe@example.com", "janedoe@example.com"])
  end
end

In this example, the let method is used to define a new User instance that is shared between all of the examples in the test case.

Which one to use depends on your specific needs. If you need to test a single instance of a class, then subject is a good choice. If you need to test multiple instances of a class, or if you need to create a new object for each example in a test case, then let is a better choice.

When to use subject

When to use let