现在我的单元测试失败了使用" Faker"公司名称。
好像expect(response.body).to match(@thing.name)
似乎搞砸了。
在查看错误时,Faker公司的名称有时会包含" O' Brian Company"或者" O' Hare Company"或类似的。
faker是编码字符串吗?因为我知道匹配编码字符串并不是一个好主意,我真的不想在Factory im中指定一个特定的公司名称。
由于
答案 0 :(得分:5)
Faker不会为你做任何编码。它只会给你一个像O'Malley
这样的字符串。但响应应该有HTML转义(或其他类型,具体取决于格式),如O'Malley
。您可以随时puts response.body
查看。
RSpec matches
匹配器的确设计为for either expected
or actual
to be a regular expression,但在您的情况下,两者都是字符串。因为代码has an optimization calling values_match?
does a simple comparison,您实际上是在说expect(response.body).to eq(@thing.name)
。
如果你想要一个正则表达式,你应该小心使用不受控制的值来创建它。幸运的是Ruby有Regexp.escape
,所以你可以说Regexp.new("foo" + Regexp.escape(@thing.name) + "bar")
。但是,从您对include
的反对意见,听起来您实际上希望响应只包含名称,对吗?在这种情况下,你根本不需要正则表达式。
在任何情况下,问题都不在于围绕这个名称,而是如何转义名称。因此,在比较之前,您应该(1)解码响应或(2)编码faker字符串。它并不重要。两者都很简单:
expect(CGI.unescapeHTML(response.body)).to eq @thing.name
或
expect(response.body).to eq CGI.escapeHTML(@thing.name)
当然,如果您的响应是JSON,那么您应该用JSON等替换所有这些HTML转义内容。
答案 1 :(得分:3)
您可以尝试使用#include而不是#match。
expect(response.body).to include(@thing.name)
答案 2 :(得分:2)
答案 3 :(得分:2)
假设您指的是Faker::Company宝石的Faker
使示例期望通过的正确方法是使用Regexp
示例中的company = Company.new(name: 'Acme Anvils')
get :show, params: {id: company.to_param}, session: {}
expect(response.body).to match(Regexp.new('Acme Anvils', Regexp::MULTILINE))
。这样做可以逃避像撇号这样的事情。
使用Faker的问题在于您的测试不是确定性的。最佳做法是为您的测试提供静态的已知输入,并期望输出根据这些输入通过某些期望。如果没有更多信息,很难提供相关的例子,但可能是这样的:
.selected
此外,您通常不应在控制器规格中测试特定的身体输出。这样做是为了跨目的进行测试。你通常会@rafael-costa。