We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.

yagudaev • 3 years ago

The issue with this setup is that it actually uploads the file, which is not something you want to do most of the time. It really slows down your test suite accessing the disk. Think how many times this Account factory will be used in your tests. Is there a way to skip all the Active Storage non-sense and just assign a filename to the attached field? (have validations I would like my model to pass)

Equivalent • 3 years ago
It really slows down your test suite accessing the disk.

So yes, in principle it slows down your tests. There is a "school of testing" where developer should isolate the layer responsible for retrieving state and just set some state in memory and test functionality (as if Repository pattern). The thing is Rails is a tightly coupled with implementation logic of state retrieval on core level and prefers "school of testing" in which you couple logic with state retrial to some degree.

Good example of this is how models are tested in Rails. You could just build entire test suite calling `FactoryBot.build` and never ever use `FactoryBot.create` and stub method all around and your tests will be lighting fast (like 5s to run your entire test suite). This is highly unproductive to achieve and I failed many times trying to achieve that because I was spending more time maintaining my tests then writing something productive for business.

Or you can took more pragmatic route and save database record where is too difficult to just 'build' the factory (e.g. Controller tests, association tests etc)

Same I would say for saving the file to the Disk. Yes you are right You could just "not save the file to disk" and save few milliseconds. But at the same time you will in future stumble upon scenarios where your tests are not passing because the file is not there (e.g. file processing validations) Is it really worth it ? I never worked on a project where saving file to a disk would slow down tests significantly enough that would be an issue (and I work for company where core business is related to file uploading) Especially now that we have SSD drives in every laptop/server it's blazing fast so at best you would save 1 seconds for entire test suite (given you call FactoryBot traits to set/store file where it make sense. Not when every time you build an object.)

there a way to skip all the Active Storage non-sense and just assign a filename to the attached field?


I'm pretty sure there is, I don't know it from top of my head as It's no value for me or my colleagues :) . But if you want to figure it out I would suggest good starting point would be: `after(:create` FactoryBot hook would create `ActiveStorage::Blog ` with `#filename` associated to your original factory model.

bo • 2 years ago

Thanks, exactly what I was looking for. One issue though: after adding the module, I get an `undefined method `upload' for nil:NilClass` error when attaching it through FactoryBot. Any ideas?

Equivalent • 2 years ago

that means you have Nil object somwhere instead of a Model. Try debugging with byebug https://github.com/deivid-r... or pry https://github.com/pry/pry ...the moment you build the fatory

Rob Nice • 3 years ago

This is super helpful! I was racking my brain on how to support 'placeholder' images for my models with Active Storage attachments just for my tests.

Manuel • 1 year ago

it's all fun and games until you get NoMethodError: undefined method `fixture_file_upload' for #<factorybot::syntaxrunner:0x00005615a171cf98>

Manuel • 1 year ago

https://github.com/thoughtb...
https://stackoverflow.com/q...

it looks like my project isn't loading the test_helper.rb

Proper solution is to use Rack::Test::UploadedFile directly in the factory (what fixture_file_upload essentially does anyway):
file { Rack::Test::UploadedFile.new('spec/factories/test.png', 'image/png') }
Gabriel Assis Ribeiro • 2 years ago

Very good!

Luis Metzger • 3 years ago

This was great, lots of help. I also did not realize I needed to require the path to the module: require "./spec/support/files_test_helper"

I kept getting an uninitalized constant error until I added this.