【问题标题】:Rspec - archives array to match tested arrayRspec - 存档数组以匹配测试数组
【发布时间】:2017-10-04 21:12:04
【问题描述】:

我的 Post 模型上有这个类方法用于获取档案

def self.archives
    Post.unscoped.select("YEAR(created_at) AS year, MONTHNAME(created_at) AS month, COUNT(id) AS total")
        .group("year, month, MONTH(created_at)")
        .order("year DESC, MONTH(created_at) DESC")
end

这是我为我的方法写的测试

context '.archives' do

  first = FactoryGirl.create(:post, published_at: Time.zone.now)
  second = FactoryGirl.create(:post, published_at: 1.month.ago)

  it 'returns articles archived' do
    archives = Post.archives()

    expect(
      [{
        year: first.published_at.strftime("%Y"),
        month: first.published_at.strftime("%B"),
        published: 1
      },
      {
        year: second.published_at.strftime("%Y"),
        month: second.published_at.strftime("%B"),
        published: 1
      }]
      ).to match_array(archives)
  end
end

但是我得到以下错误

expected collection contained:  [#<Post id: nil>, #<Post id: nil>]
actual collection contained:    [{:year=>"2017", :month=>"October", :published=>1}, {:year=>"2017", :month=>"September", :total=>1}]
the missing elements were:      [#<Post id: nil>, #<Post id: nil>]
the extra elements were:        [{:year=>"2017", :month=>"October", :total=>1}, {:year=>"2017", :month=>"September", :total=>1}]

所以虽然我创建了 2 个工厂,但 archives 数组是空的。我做错了什么?

【问题讨论】:

    标签: ruby-on-rails ruby unit-testing rspec rspec-rails


    【解决方案1】:

    Rspec 标准是使用let 语法在上下文或描述块中定义变量。测试应该如下所示:

    describe '.archives' do
      let!(:first) { FactoryGirl.create(:post, published_at: Time.zone.now) }
      let!(:second) { FactoryGirl.create(:post, published_at: 1.month.ago) }
    
      it 'returns year, month, and total for articles archived' do
        actual_attributes = Post.archives.map { |post| [post.year, post.month, post.total] }
        expected_total = 1 # I don't know why the query is returning 1 for total, but including this for completeness
        expected_attributes = [first, second].map { |post| [post.created_at.year, post.created_at.strftime("%B"), expected_total] }
    
        expect(actual_attributes).to match_array(expected_attributes)
      end
    end
    

    这里的问题是,您将仅使用少数属性(SQL 查询的结果)提取的记录与完整格式的记录(由您的测试创建)进行比较。该测试从两组中提取适用的属性并进行比较。

    【讨论】:

    • expected collection contained: [#&lt;Post id: nil&gt;, #&lt;Post id: nil&gt;]actual collection contained: [#&lt;Post id: 1, user_id: 4, title: "This is the Post title", excerpt: "This is the Post body", created_at: "2017-10-04 21:25:31", updated_at: "2017-10-04 21:25:31"&gt;]
    • 我稍微调整了一下。请重试。
    • 我自己尝试过反转数组,但没有任何变化
    • 您是否在let 之后添加了!
    • 尝试添加已编辑答案中显示的额外期望,并告诉我它是在第一个期望还是第二个期望失败。
    【解决方案2】:

    实际数组不为空,它是两个未设置 id 的 Post 实例的数组(因为 .archives 方法中的 Select 不包含 id 字段)。 您可以将预期的哈希值与archives 进行比较,而不是像这样:

    actual = Post.archives().map do |post| 
      { year: post["year"].to_s, month: post["month"], published: post["total"] }
    end
    
    expected = [{
      year: first.published_at.strftime("%Y").to_s,
      month: first.published_at.strftime("%B"),
      published: 1
    },
    {
      year: second.published_at.strftime("%Y").to_s,
      month: second.published_at.strftime("%B"),
      published: 1
    }]
    
    expect(actual).to match_array(expected)
    

    【讨论】:

    • 不确定我是否理解,你的意思是这应该代替我的expect
    • 澄清了答案。
    • expected collection contained: [{:year=&gt;"2017", :month=&gt;"October", :published=&gt;1}, {:year=&gt;"2017", :month=&gt;"September", :published=&gt;1}]actual collection contained: []the missing elements were: [{:year=&gt;"2017", :month=&gt;"October", :published=&gt;1}, {:year=&gt;"2017", :month=&gt;"September", :published=&gt;1}]
    • let! 我得到actual collection contained: [{:year=&gt;2017, :month=&gt;"October", :published=&gt;1}, {:year=&gt;2017, :month=&gt;"September", :published=&gt;1}] the missing elements were: [{:year=&gt;"2017", :month=&gt;"October", :published=&gt;1}, {:year=&gt;"2017", :month=&gt;"September", :published=&gt;1}] the extra elements were: [{:year=&gt;2017, :month=&gt;"October", :published=&gt;1}, {:year=&gt;2017, :month=&gt;"September", :published=&gt;1}]
    • 实际集合中包含年份为整数,应转换为字符串
    猜你喜欢
    • 2020-02-17
    • 2014-07-12
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-29
    相关资源
    最近更新 更多