I was thinking about how to not rely on the database in the test a few years ago, but I have not found a viable solution. Seeing this article today, I feel that the proposal proposed by the author seems to be feasible and relatively simple.
How to test that you are creating a record without using the database
I simply verified it, no problem.
I plan to do a real project verification later.
class Product < ActiveRecord::Base
end
store = Product
Catalog.add_product(attrs, store)
This is an example. The advantage of this is that it is more readable, you can simulate the store to avoid database testing.
Hey this is the test code
###
class DummyProductsStore
Def self.create(attrs)
End
end
def store
DummyProductsStore
end
###
it "creates a record" do
attrs = { name: "P1", description: "Super Product" }
# This is the code that expects "store.create(attrs)" to be called
expect(store).to receive(:create).with(attrs)
Catalog.add_product(attrs, store)
end
In the code, store is used instead of Product, and the store is replaced when testing.
I used the rspec test to be feasible, but the problem is that the verification code is not executed after the simulation, I don't know how to solve it.
Clean Architecture
As shown in the figure, the business model should be centered, the use case organizes the code, and the controller and database should be peripheral interfaces.
I feel that this code is to make the model as the entity, the corresponding Product class and class method as the database interface. Closer to the architectural idea of the illustration. The original rails are organized with data as the center, or the database is the center.
Clean Architecture Description
Look at the code, how do you feel? Please see the original code for the detailed code.
Top comments (5)
Hi @chenge , thanks for sharing my article =) ... although apparently the link is broken dev.to/bhserna/how-to-test-that-yo...
About the verification code...
I think that what Leonardo said is a good solution... I prefer the other just because you don't need to write
allow(store).to receive(:create)
before.Other option is to create a custom "spy" that can do whatever you want, like...
But I think that in this case I prefer the other two solutions.
Abut the clean architecture reference...
Yes! this is more or less what I do and propose... To use the model more or less like an entity and the Product class as the Database interface.
Nice post!!! That's unit test!! =DD
I'll give another way to test, but, using the rspec matcher
have_received
because it seems more readable. See the example below usinghave_received
matcher and tell me what do you think, ok? =)see more about have_received matcher
Thanks for reply. Here my main focus is how to run validation code while testing.
I'm a new comer for rspec so I cannot say too much about it.
We have recently began relying on collection based repositories for functional tests (they store data/objects in memory, instead of saving it in the database). Unit tests should receive mock database connections and return mock data for database calls.
The idea is to split the testing environment into non persistent and persistent. This way you only test the database related bits when you know the code is working properly.
Yes, agree.