新手问题 测试一个组合的唯一性,我在数据库层面增加了组合 unique 但是测试有问题

yirolhao · February 28, 2017 · Last by yirolhao replied at February 28, 2017 · 1952 hits

测试一个组合的唯一性,我在数据库层面增加了组合 unique。 但是测试有问题:

def setup
  @like = Like.new(liker_id: 1, liked_article_id: 1)
end

test "liker-id and liked-article-id unique" do
  assert @like.valid? 
  assert @like.save
  @other = @like.dup
  assert_not @other.save
end

没有通过,但是在 Rails Console 中可以:

@like = Like.new(liker_id: 1, liked_article_id: 1)
@like.valid?
@like.save 
@other = @like.dup
@other.save #失败

like.rb

class Like < ApplicationRecord
  belongs_to :liker, class_name: "User"
  belongs_to :liked_article, class_name: "Article"
  validates :liker_id, presence: true
end

之前运行测试的时候出现了错误,让我运行 rails env=test 或者 env=development 大概这样,记不清了。 我运行了第一个,然后执行了迁移。

--------------------------------解决 按照 @lithium4010 说的:

liker liked article 必须关联上

测试环境数据库没有 id 为 1 的 liker 和 liked_article

进行如下修改:

def setup
  @user = User.create(name:"kaka",email: "[email protected]",
                          password_digest: User.digest('password'))
  @article = @user.articles.create(title: "mysq",content: "kakarot")
   @like = Like.new(liker_id: @user.id, liked_article_id: @article.id)
end

test "liker-id and liked-article-id unique" do
    Like.destroy_all
    assert @like.valid? 
    assert @like.save
    @other = Like.new(liker_id: @user.id, liked_article_id: @article.id)
    assert_not @other.save
    assert @user.destroy
    assert @article.destroy
end

原谅我不知道这里固件应该怎么用。

感谢 @kai209209 @lithium4010

你 model 的代码不发出来看看吗

Reply to kai209209

好,但是我的 model 其实没有什么东西的。

你这 model 只是定义了 like_id 必须存在,并没有组合唯一性的代码

Reply to kai209209

但是 assert @like.valid? 也没有通过。

你添加这个代码

validates :liker, uniqueness: { scope: :liked_article}


然后测试一下

Reply to kai209209

没有用,还是没通过,这个是什么意思?我没有 liker 这一列

like 就是 like_id 啊

完整的写就是这样:validates :liker_id, uniqueness: { scope: :liked_article_id}

_id 可以省

Reply to kai209209

但是验证还是没有办法通过。

Reply to yirolhao

你测试数据库表里面的数据在你测试完后会自动删除掉数据吗?

Reply to kai209209

应该是不会自动删除,因为 demo_test 数据库里 users 表里面有数据,但是 likes 表里面没有数据。

我刚刚新建了一个跟你一样代码的项目做了测试,似乎就是你测试数据库里的 like 表的数据没有清除导致的。 like 里面添加 validates :liker_id, uniqueness: { scope: :liked_article_id} 然后我这里测试通过了

Reply to yirolhao

你测试改这样

def setup
  @like = Like.new(liker_id: 1, liked_article_id: 1)
end

test "liker-id and liked-article-id unique" do
  Like.destroy_all
  @like.valid?
  assert @like.valid? 
  assert @like.save
  @other = Like.new(liker_id: 1, liked_article_id: 1)
  assert_not @other.save
end
Reply to kai209209

但我的 likes 表是空的,我看了 test 数据库。或者怎么样在清除一次?reset?

Reply to kai209209

还是不行。。😭 😭 还是原来的错误,都是 false 这样才能通过。

Like.destroy_all
assert_not @like.valid? 
assert_not @like.save
@other = Like.new(liker_id: 1, liked_article_id: 1)
assert_not @other.save

会不会是我选择 env 的问题?

Reply to yirolhao

你改成这样

test "liker-id and liked-article-id unique" do
  Like.destroy_all
  @like.valid?
  p "111!!!!#{@like.valid?}"
  assert @like.valid? 
  assert @like.save
  p "2222!!!!!#{@like.attributes}"
  @other = Like.new(liker_id: 1, liked_article_id: 1)
  p "3333!!!!#{@other.valid?}"
  p "4444!!!!#{@other.errors.messages}"
  assert_not @other.save
end

然后看看输出是什么?

我这里输出是这样的

Reply to kai209209

rails test 之后,就只 Failure 没有其他错误信息了,话说还能这么用,我一直是在 console 里面,这么看。

p "111!!!!#{@like.valid?}"
p "@like errors: #{@like.errors.messages}"

添加一行,看看输出的是什么错误

Reply to kai209209

让通过之后的。

Reply to kai209209
"{:liker=>[\"must exist\"], :liked_article=>[\"must exist\"]}"

这不是在 new 的时候都有的吗?。。。

Reply to yirolhao
test "liker-id and liked-article-id unique" do
  Like.destroy_all
  @like.valid?
  p "111!!!!#{@like.valid?}"
  p "@like errors: #{@like.errors.messages}"
  assert @like.valid? 
  assert @like.save
  p "2222!!!!!#{@like.attributes}"
  @other = Like.new(liker_id: 1, liked_article_id: 1)
  p "3333!!!!#{@other.valid?}"
  p "4444!!!!#{@other.errors.messages}"
  assert_not @other.save
end

你测试用例改这样啊,看@like输出的的错误是什么

Reply to kai209209

我上面那个就是输出的错误,我加了之后的。

你测试数据库迁移了吗?你到命令行下执行 rails db:migrate RAILS_ENV=test,然后再测试

Reply to kai209209

对,上次我就运行的这条命令,然后迁移,我在看看

Reply to kai209209

运行了,没有任何返回,貌似没有没迁移的文件。运行测试还是如以前一样的结果。😭

你项目里面没有迁移文件的?

Reply to kai209209

我的意思是说,所有的文件都已经迁移过了。运行,ails db:migrate RAILS_ENV=test 没有反应。

https://github.com/kai209209/like 我把我做的放到 github 里了,你看看跟你项目的 like 有没有什么区别吧

Reply to kai209209

没什么区别,要说区别的话,只有 user 和 article

article.rb

has_many :passive_likes, class_name:  "Like",
                         foreign_key: "liked_article_id",
                         dependent:   :destroy
has_many :liked_article, through: :passive_likes 

user.rb

has_many :active_likes, class_name:  "Like",
                        foreign_key: "liker_id",
                        dependent:   :destroy
has_many :liker, through: :active_likes

liker liked article 必须关联上

测试环境数据库没有 id 为 1 的 liker 和 liked_article

Reply to lithium4010

我数据库里也没有 liker 和 liked_article,但是我的能通过

Reply to lithium4010

我在回宿舍路上,回去看看。新建一个吗?

Reply to yirolhao

你测试里面是不是还有什么别的代码啊?

Reply to kai209209

没有,就那个。

Reply to yirolhao

不知道你项目具体代码是怎么样的,无法排出问题

Reply to kai209209

按照 @lithium4010 他说的,我改了之后好了。

def setup
  @user = User.create(name:"kaka",email: "[email protected]",
                          password_digest: User.digest('password'))
  @article = @user.articles.create(title: "mysq",content: "kakarot")
   @like = Like.new(liker_id: @user.id, liked_article_id: @article.id)
end

test "liker-id and liked-article-id unique" do
    Like.destroy_all
    assert @like.valid?
    assert @like.valid? 
    assert @like.save
    @other = Like.new(liker_id: 1, liked_article_id: 1)
    assert_not @other.save
    assert @user.destroy
    assert @article.destroy
  end
Reply to kai209209

不知道固件这里应该怎么用,就只能酱紫了。

难道这个测试还跟数据库有关?我用的是 sqllite3,你这里用的是什么数据库

Reply to kai209209

mysql 数据库

Reply to yirolhao

有个 gem 可以测试完后自动删除测试数据的,你就不用写个 Like.destroy_all 上去了,而且测试数据一般在测试完后都是要删的

Reply to kai209209

哪个 gem?

Reply to yirolhao

gem 'database_cleaner' 放到 test 的 group 里面

Reply to kai209209

好的,我去看看。

You need to Sign in before reply, if you don't have an account, please Sign up first.