19

How would go about writing proper unit testing (and integration testing for that matter) using MongoDB through Mongoid on Rails ?

I am asking, because to the opposite of using let's say SQLite3, even when running tests, everything I do does persists. So for the moment I am writing the creation test and then I manually delete everything I do. But it's getting annoying and even complicated to do for integration testing.

Sample of what I do:

before(:each) do
  @user = User.create!(@attr)
end

after(:each) do
  # MongoDB is not a transactional DB, so added objects (create) during tests can't be rollbacked
  # checking for the existance of a similar object with exact :name and :email (regex make it case insensitive)
  cleanup = User.where(:name => "Example User", :email => /^user@example.com/i)
  cleanup.destroy unless cleanup.nil?
end

Any idea how to make MongoDB not persistent during Testing ? (I can't even run the console in sandbox mode because to use Mongoid I had to deactivate Active Record).

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
Alex
  • 4,367
  • 5
  • 29
  • 45

5 Answers5

12

Ok thanks to Kyle who pointed me in the right direction, I found out how to make it work.

So basically the trick is to drop all your collections in mongodb for each test case that you will run. This is a bit radical, but it works. But keep in mind that you won't retain any data at all in you test db.

Finally I found that link: http://adventuresincoding.com/2010/07/how-to-configure-cucumber-and-rspec-to-work-with-mongoid

And basically what you need to do is simple:

add a block in you spec_helper.rb:

RSpec.configure do |config|

# blabla other confs

  config.before :each do
    Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
  end

# blabla other confs

end

For Mongoid 3:

 Mongoid.default_session.collections.select {|c| c.name !~ /system/ }.each(&:drop

This effectively kills all the collection within the db allowing you to run your tests fresh every time.

Alex

Adrian
  • 9,102
  • 4
  • 40
  • 35
Alex
  • 4,367
  • 5
  • 29
  • 45
5

Another way is to use database_cleaner. It supports multiple ORMs, so I think you could do something like this:

# spec/support/database_cleaner.rb
RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner[:mongoid].strategy = :truncation
    DatabaseCleaner[:mongoid].clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end
Zubin
  • 9,422
  • 7
  • 48
  • 52
4

There's no way to make MongoDB non-persistent. You simply have to delete data before or after each test. There's some documentation on that here:

http://www.mongodb.org/display/DOCS/Rails+-+Getting+Started#Rails-GettingStarted-Testing

Kyle Banker
  • 4,359
  • 23
  • 18
  • Thanks, that's what I was afraid of... Good link though, I thought I have read through the complete mongoDB pages, but not yet apparently :) I'll try that solution to avoid having to add manual code every time I am writing test. – Alex Jan 15 '11 at 05:25
2

Here's what I did (using Test::Unit and Mongoid 3)...

# test/test_helper.rb
setup {
  Mongoid.default_session.collections.select {|c| c.name !~ /system/ }.each(&:drop)
}
Lucas Pottersky
  • 1,844
  • 6
  • 22
  • 38
2

This one worked for me.

In spec_helper.rb, under RSpec.configure do |config| I put:

config.before :each do
   Mongoid.purge!
end

Reference.

Askar
  • 5,784
  • 10
  • 53
  • 96