2012-06-27 39 views
3

我正在rails中创建一个REST API。我正在使用RSpec。我想尽量减少数据库调用的次数,所以我想添加一个自动测试来验证作为特定操作的一部分而正在执行的数据库调用的数量。 是否有一种简单的方法将其添加到我的测试中? 我正在寻找的是一种方法来监视/记录由于单个API调用而对数据库进行的调用。 如果这不能用RSpec完成,但可以用其他测试工具完成,那也很棒。如何测试Rails中的数据库调用次数

回答

2

最容易的事情中的Rails 3可能是钩到通知API。

该用户

class SqlCounter< ActiveSupport::LogSubscriber 

    def self.count= value 
    Thread.current['query_count'] = value 
    end 

    def self.count 
    Thread.current['query_count'] || 0 
    end 

    def self.reset_count 
    result, self.count = self.count, 0 
    result 
    end 

    def sql(event) 
    self.class.count += 1 
    puts "logged #{event.payload[:sql]}" 
    end 
end 

SqlCounter.attach_to :active_record 

将打印每一个执行的SQL语句到控制台和计数。然后,您可以编写规范,如

expect do 
    # do stuff 
end.to change(SqlCounter, :count).by(2) 

您可能需要过滤掉一些语句,比如那些开始/提交事务或那些活动记录发出来确定表的结构。

0

Fredrick的回答对我很好,但在我的情况下,我也想知道每个ActiveRecord类的调用个数。我做了一些修改,并以此为结束,以防其他人使用。

class SqlCounter< ActiveSupport::LogSubscriber 

    # Returns the number of database "Loads" for a given ActiveRecord class. 
    def self.count(clazz) 
    name = clazz.name + ' Load' 
    Thread.current['log'] ||= {} 
    Thread.current['log'][name] || 0 
    end 

    # Returns a list of ActiveRecord classes that were counted. 
    def self.counted_classes 
    log = Thread.current['log'] 
    loads = log.keys.select {|key| key =~ /Load$/ } 
    loads.map { |key| Object.const_get(key.split.first) } 
    end 

    def self.reset_count 
    Thread.current['log'] = {} 
    end 

    def sql(event) 
    name = event.payload[:name] 
    Thread.current['log'] ||= {} 
    Thread.current['log'][name] ||= 0 
    Thread.current['log'][name] += 1 
    end 
end 

SqlCounter.attach_to :active_record 

expect do 
    # do stuff 
end.to change(SqlCounter, :count).by(2)