This way you can guarantee the controller produces API values even if
bunch of methods get override.

We are truly expecting a “string value” not just result of a method.

Yes there is always a level on what can be tested this way. I’m just
saying when possible try to work with plain values in tests.

There are times you want to compare two objects expect(my_obj).to be(my_obj).
But you really need to have a reason to describe the test this way not do it by default.

And yes it may lead to more “brittle tests” (tests that fail for minor changes) but at least those tests prove the result.

In accounting profession the act of “bookkeeping” reflects upon checking
the “debits” and “credits”. Debits (on left side of spreadsheet) must equal Credits (on right side of spreadsheet).
Imagine Debit is like your code, Credit is like your test that would prove that you
didn’t loose money.

Now imagine your code is a $1 000 000 worth Debit. You will try your
darn best to make sure that the test you write would be as accurate as
possible.

Would you just work with estimates: “We had sales around 1 000 000 and we needed to pay around 900 000 for material and 100 000 salaries, it should be fine”)

If we would create the user object with let(:user) { User.create name: Faker::Name.first_name } we would end up
with random name each time therefore the 2nd version of the test would fail.

I fully respect testing with random data as that helps discovering of
errors normally developers have no chance to. The thing however is
that lot of developers miss the point that they should be testing random
data like object type + object value compare:

No it’s not stupid it’s just different flavor of testing with more OOP
involved in the test code. You need to realize if you going to mix OOP principles into the
test code recipe you need to test the objects on several layers.

Don’t get me started on stubbing methods interfaces in controllers, that’s an article
for several pages

My point is YES you can write your tests as a OOP code. But you need to
fully take responsibility in what parts of your test code may the
object values change as you are not the only one who is contributing to
the project code.

Or you can write more simple tests with more primitive values (strings,
integers) and skip a layer or two of tests.

Ecosystem of Rails ?

Although I use and respect notion of object oriented decoupling,
mocking school of testing, re-usability of code (even within tests) unit
testing, SOLID principles, etc; the
truth is lot of times if you don’t fully understnad what you are doing it will leave your code like this:

…especially with Rails.

There are historic and architectural reasons around Ruby on Rails (not
Ruby, just Rails !) where authors took “decouple OOP” shortcuts in favor of
productivity. This also apply to mindset of developers working with it.