【发布时间】:2011-07-28 09:11:34
【问题描述】:
我对 rspec 和 rails 有一些奇怪的问题。所以我有模型测试:
require 'spec_helper'
describe User do
before(:each) do
@attr = { name: "johnkowalski", fullname: "John Kowalski",
email: "kowalski@example.com", password: "foobar" }
end
describe "Create a user" do
it "test1" do
User.create!(@attr)
end
it "test2" do
User.create!(@attr)
end
it "test3" do
User.create!(@attr)
@p = { name: "testowy", fullname: "John Kowalski",
email: "kowalski@example.com", password: "foobar" }
a = User.new(@p)
a.should_not be_valid
end
it "test4" do
User.create!(@attr)
end
end
end
它通过没有问题,但是当我添加一些集成测试时:
require 'spec_helper'
describe "Users" do
describe "signup" do
describe "failure" do
it "should not make a new user" do
lambda do
visit signup_path
fill_in "Name", with: ""
fill_in "Full name", with: ""
fill_in "Email", with: ""
fill_in "Password", with: ""
click_button
response.should render_template("users/new")
response.should have_selector("div#error_explanation")
end.should_not change(User, :count)
end
end
end
end
我有失败:
Failures:
1) Users signup failure should not make a new user
Failure/Error: visit signup_path
AbstractController::ActionNotFound:
The action 'new' could not be found for UsersController
# ./spec/requests/users_spec.rb:8:in `block (5 levels) in <top (required)>'
# ./spec/requests/users_spec.rb:7:in `block (4 levels) in <top (required)>'
2) User Create a user test4
Failure/Error: User.create!(@attr)
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken
# ./spec/models/user_spec.rb:28:in `block (3 levels) in <top (required)>'
Finished in 0.77216 seconds
5 examples, 2 failures
第一次失败很明显(我的控制器是空的)但为什么第二次发生?另外,如果我进行了通过的集成测试,则模型测试也通过了。我使用 rails 3.1.0.rc5 和 rspec 2.6.4。即使当我评论 a.should_not be_valid 行时,它也可以工作。完全看不懂。
编辑: 我知道这是验证问题,但为什么 test4 在此示例中有效:
require 'spec_helper'
describe User do
before(:each) do
@attr = { name: "johnkowalski", fullname: "John Kowalski",
email: "kowalski@example.com", password: "foobar" }
end
describe "Create a user" do
it "test1" do
User.create!(@attr)
end
it "test2" do
User.create!(@attr)
end
it "test3" do
User.create!(@attr)
@p = { name: "testowy", fullname: "John Kowalski",
email: "kowalski@example.com", password: "foobar" }
a = User.new(@p)
a.should_not be_valid
end
it "test4" do
User.count.should == 0
end
it "test5" do
User.create!(@attr)
end
end
end
用户.rb:
class User < ActiveRecord::Base
has_secure_password
email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, presence: true, length: { maximum: 20 },
uniqueness: { case_sensitive: false }
validates :fullname, presence: true, length: { maximum: 30 }
validates :email, format: { with: email_regex },
uniqueness: { case_sensitive: false }, length: { maximum: 30 }
validates :password, length: { in: 5..25 }
end
我找到了这些事情发生的原因。所以当我只运行模型测试时,我在日志中有类似的东西:
(0.0ms) RELEASE SAVEPOINT active_record_1
(0.1ms) SELECT 1 FROM "users" WHERE LOWER("users"."name") = LOWER('testowy') LIMIT 1
(0.1ms) SELECT 1 FROM "users" WHERE LOWER("users"."email") = LOWER('kowalski@example.com') LIMIT 1
(0.1ms) SELECT COUNT(*) FROM "users"
(0.1ms) SAVEPOINT active_record_1
(0.1ms) SELECT 1 FROM "users" WHERE LOWER("users"."name") = LOWER('johnkowalski') LIMIT 1
(0.1ms) SELECT 1 FROM "users" WHERE LOWER("users"."email") = LOWER('kowalski@example.com') LIMIT 1
SQL (0.3ms) INSERT INTO "users" ("created_at", "email", "fullname", "name", "password_digest", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["created_at", Thu, 28 Jul 2011 13:09:48 UTC +00:00], ["email", "kowalski@example.com"], ["fullname", "John Kowalski"], ["name", "johnkowalski"], ["password_digest", "$2a$10$e1.3fifGcs7PALH1o0GQJ.Ny/QxCS9fRxDJ6NemGkwfFJCpsD51vy"], ["updated_at", Thu, 28 Jul 2011 13:09:48 UTC +00:00]]
(0.0ms) RELEASE SAVEPOINT active_record_1
但是当我运行这些测试和集成测试时,我在日志中发现了这一点:
(0.1ms) SELECT 1 FROM "users" WHERE LOWER("users"."email") = LOWER('kowalski@example.com') LIMIT 1
(0.1ms) SELECT COUNT(*) FROM "users"
(0.1ms) SAVEPOINT active_record_1
(0.1ms) SELECT 1 FROM "users" WHERE LOWER("users"."name") = LOWER('johnkowalski') LIMIT 1
CACHE (0.0ms) SELECT 1 FROM "users" WHERE LOWER("users"."email") = LOWER('kowalski@example.com') LIMIT 1
(0.0ms) ROLLBACK TO SAVEPOINT active_record_1
所以用户对象是从内存而不是从数据库中获取的。但默认情况下,缓存在测试环境中被禁用,我有 config.action_controller.perform_caching = false 在环境/test.rb
在这种情况下如何禁用缓存?
【问题讨论】:
-
这真的很奇怪,你在模型中进行了哪些验证?
-
GAH,不要使用
test1和test2作为你的测试名称! rSpec DSL 的全部意义在于你应该用类似于自然语言的方式来描述你的测试。而不是it "test1",您应该始终使用it "should be invalid"或其他一些实际描述性名称。
标签: ruby-on-rails ruby-on-rails-3 rspec