# 为自定义路径/模型编写 put 规范

**URL:** https://meta.discourse.org/t/writing-specs-for-put-to-a-custom-path-model/168653
**Category:** Development
**Created:** [2020年十月29日 16:22 UTC](https://meta.discourse.org/t/writing-specs-for-put-to-a-custom-path-model/168653 "2020-10-29T16:22:11Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十月29日 16:22 UTC](https://meta.discourse.org/t/writing-specs-for-put-to-a-custom-path-model/168653/1 "2020-10-29T16:22:11Z")

</div>

我正在开发一个添加模型的插件。我试图编写测试规范，以验证模型（以及控制器？）的行为是否符合预期。

这段 Ansible 库中的代码成功地向该路径执行了 `PUT` 请求，并更新了模型/记录中的字段：

```python
    headers = {
        'Api-Key': discourse_api_key,
        'Api-Username': discourse_api_username,
    }

    payload = {
        "server[request_status]": status
    }
    url = "%spfaffmanager/servers/%s" % (discourse_url, server_id)

    # raise Exception(url) 
    result = requests.put(url, data=payload, headers=headers)

```

这是我正在编写的用于测试该路径更新的规范。我感到困惑，因为我在控制器中有无数个 `puts`，但没有任何一个打印出来，尽管在模型中（例如在 `before_save` 调用的函数中）的 `puts` 却显示在我看到的 `rake autospec` 输出中。

我最大的猜测是我搞错了：

```ruby
# frozen_string_literal: true
require 'rails_helper'

describe Pfaffmanager::ServersController do
  fab!(:user) { Fabricate(:user) }
  fab!(:admin) { Fabricate(:admin) }
  fab!(:another_user) { Fabricate(:user) }
  fab!(:trust_level_2) { Fabricate(:user, trust_level: TrustLevel[2]) }
  before do
    Jobs.run_immediately!
  end

  it 'can update status' do
    request_status = 'new status'
    sign_in(admin)
    s=Pfaffmanager::Server.createServerFromParams(user_id: user.id,
        hostname: 'bogus.invalid' , request_status: 'not updated')
    puts "can update status created server id: #{s.id}"
    params = {server: {request_status: request_status}}
    
    expect {
        put "/pfaffmanager/servers/#{s.id}", params: params
    }.to change { s.request_status }
    expect(response.status).to eq(200)
    expect(s.request_status).to eq('new status')
  end
end

```

昨天我几乎花了一整天时间，非常希望能得到任何关于解决方案或调试技巧的提示。

---

<div class="post-metadata">

### Author: ![justin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/justin/32/157614_2.png) [@justin](https://meta.discourse.org/u/justin)
#### Post date: [2020年十月29日 18:31 UTC](https://meta.discourse.org/t/writing-specs-for-put-to-a-custom-path-model/168653/2 "2020-10-29T18:31:16Z")

</div>

如果 `s=Pfaffmanager::Server.createServerFromParams(user_id: user.id, hostname: 'bogus.invalid' , request_status: 'not updated')` 是你创建的模型，那么为了让请求测试正常运行，你可能需要像之前示例中伪造用户那样，为它创建伪造数据。

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十月29日 21:00 UTC](https://meta.discourse.org/t/writing-specs-for-put-to-a-custom-path-model/168653/3 "2020-10-29T21:00:37Z")

</div>

哦，所以问题可能在于我使用了 fabricate 而不是实际创建？在其他测试中，例如，我会用上述代码创建一个 `Server`，然后执行 `get` 来获取服务器列表，确认存在具有正确主机名的服务器，并验证返回的服务器数量是否正确。

不过，弄清楚如何以“正确”的方式 fabricate 一个对象可能更有意义。

非常感谢你的帮助！我接下来就试试这个方法！

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十一月12日 14:19 UTC](https://meta.discourse.org/t/writing-specs-for-put-to-a-custom-path-model/168653/4 "2020-11-12T14:19:50Z")

</div>

我找到了我的问题（至少是其中之一）。如果你的 `model.rb` 文件中有错误，比如尝试执行类似 `variable_that_is_nil['xxx']` 的操作，模型会失败，但 spec 日志中不会像你在浏览器中“测试”时在 Rails 日志中看到的那样显示任何错误。因此，这可能会让你误以为模型或控制器没有被调用，而实际上它们已经被调用了。

不过，我确实编写了一个真正的 `Fabricator`，所以感谢你的推动，@justin！
