如何断言数组的内容,对顺序无动于衷

 MIKO_CHEUNG2011 发布于 2023-02-13 13:58

我有一个最小的规格:

it "fetches a list of all databases" do
  get "/v1/databases"
  json = JSON.parse(response.body)
  json.length.must_equal           Database.count
  json.map{|d| d["id"]}.must_equal Database.all.pluck(:id)
end

但是,这失败了:

Expected: [610897332, 251689721]
  Actual: [251689721, 610897332]

我可以同时订购它们,但这会增加混乱:

json.map{|d| d["id"]}.sort.must_equal Database.all.pluck(:id).sort

事实上,它map{}已经与测试有点无关并且增加了混乱,我宁愿不再添加更多.

是否有断言或助手来测试是否所有物品enumerator1都在enumerator2

2 个回答
  • MiniTest Rails Shoulda具有一个assert_same_elements断言,该断言:

    断言两个数组包含相同的元素,相同的次数。本质上==,但无序。

    assert_same_elements([:a, :b, :c], [:c, :a, :b]) => passes
    

    2023-02-13 14:01 回答
  • TL; DR检查这个问题的最直接方法是在检查数组之前对数组进行排序.

    json.map{|d| d["id"]}.sort.must_equal Database.all.pluck(:id).sort
    

    还在?好的.我们来谈谈比较数组中的元素.

    事实上,地图{}已经与测试有点无关并且增加了混乱,我宁愿不再添加更多.

    嗯,这是问题的一部分.您的JSON包含一个JSON对象数组,而调用Database.pluck将返回其他内容,可能是整数.您需要将JSON对象和查询转换为相同的数据类型.所以说这.map{}是无关紧要是不准确的,如果它感觉像是混乱,那就是因为你在断言中做了很多事情.尝试拆分该行代码并使用意图揭示名称:

    sorted_json_ids = json.map{|d| d["id"]}.sort
    sorted_db_ids   = Database.order(:id).pluck(:id)
    sorted_json_ids.must_equal sorted_db_ids
    

    在测试中有更多的代码行,但更好地传达了意图.然而,我听到你的话语"无关紧要"和"混乱"在我脑海中回荡.我打赌你不喜欢这个解决方案."它的工作太多了!" 并且"为什么必须对此负责?" 好吧好吧.我们有更多选择.更智能的断言怎么样?

    RSpec有一个很好的小匹配器match_array,可以满足您的需求.它对数组进行排序和比较,如果它们不匹配则打印出一条好消息.我们可以做类似的事情.

    def assert_matched_arrays expected, actual
      assert_equal expected.to_ary.sort, actual.to_ary.sort
    end
    
    it "fetches a list of all databases" do
      get "/v1/databases"
      json = JSON.parse(response.body)
      assert_matched_arrays Database.pluck(:id), json.map{|d| d["id"]}
    end
    

    "但这是一个断言而不是期望!" 是的,我知道.放松.您可以通过调用将断言转换为期望infect_an_assertion.但要做到这一点,您可能希望添加断言方法,以便可以在每个Minitest测试中使用它.所以在我的test_helper.rb文件中我添加以下内容:

    module MiniTest::Assertions
      ##
      # Fails unless <tt>exp</tt> and <tt>act</tt> are both arrays and
      # contain the same elements.
      #
      #     assert_matched_arrays [3,2,1], [1,2,3]
    
      def assert_matched_arrays exp, act
        exp_ary = exp.to_ary
        assert_kind_of Array, exp_ary
        act_ary = act.to_ary
        assert_kind_of Array, act_ary
        assert_equal exp_ary.sort, act_ary.sort
      end
    end
    
    module MiniTest::Expectations
      ##
      # See MiniTest::Assertions#assert_matched_arrays
      #
      #     [1,2,3].must_match_array [3,2,1]
      #
      # :method: must_match_array
    
      infect_an_assertion :assert_matched_arrays, :must_match_array
    end
    

    现在您的断言可用于任何测试,您的期望将在每个对象上可用.

    it "fetches a list of all databases" do
      get "/v1/databases"
      json = JSON.parse(response.body)
      json.map{|d| d["id"]}.must_match_array Database.pluck(:id)
    end
    

    2023-02-13 14:01 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有