Ruby 测试期望运行一个命令
Posted
技术标签:
【中文标题】Ruby 测试期望运行一个命令【英文标题】:Ruby testing expect a command to be ran 【发布时间】:2013-08-21 08:50:42 【问题描述】:我使用 Minitest 和 Mocha 测试我的 Rails 应用程序以进行单元测试和集成测试,并想测试是否使用某些参数调用命令行命令。
说,我有课:
class Provisioning::Backup
def create(path)
system("tar -czf #path bar.tar.gz")
end
end
我的测试只有想知道带有这些参数的命令是否运行。而不是它是否使用system()
或它的替代品``
。甚至通过resque等。我想测试外部,而不是内部实现。
因此,我对 *test/integration/user_requests_backup_test.rb* 中的当前解决方案不满意:
class UserRequestsBackupTest < ActionDispatch::IntegrationTest
test "requests for a backup runs a backup-script" do
contact = contacts(:harry)
site = contact.sites.first
Provisioning::Backup.expects(:system).with("tar -xzf foo bar")
post "/v1/sites/#site.id/backups"
assert_response :success
end
# backup is already pending
# backup fails
end
这可行,但断言实现而不是行为,因为Provisioning::Backup.expects(:system).with("tar -xzf foo bar")
对内部工作假设过多,并且一旦我将其移至例如回复
我还有哪些其他选择?有没有办法模拟或存根并期望 system
在较低级别?是否存在允许以更通用的方式模拟和预期命令的模式或 gem?
【问题讨论】:
【参考方案1】:有一条经验法则,您应该“只模拟您拥有的对象”。在这种情况下,您似乎希望确保创建了压缩存档。您可能应该在应用程序的某个地方有一个对象或方法,其唯一责任是执行此操作。
假设您有一个名为create_archive
的方法来执行此操作。在create_archive
上使用适当的单元测试覆盖率,您可以简单地验证它是从您的集成测试中调用的。
您应该期望并验证是否调用了此方法,而不是调用 Kernel#system
或 Kernel#`
。这些调用是实现细节,您想验证逻辑 (create_archive
)。
class UserRequestsBackupTest < ActionDispatch::IntegrationTest
test "requests for a backup runs a backup-script" do
contact = contacts(:harry)
site = contact.sites.first
Provisioning::Backup.expects(:create_archive)
post "/v1/sites/#site.id/backups"
assert_response :success
end
end
【讨论】:
【参考方案2】:您所做的是集成测试。您还需要一个不关心 system
方法的结果的低级单元测试,但要确保它会被正确调用。
我只知道使用 rspec-mock 模块的 Rspec 方法,但不知道 minitest。
describe Provisioning::Backup do
subject Provisioning::Backup.new
it "calls system method correctly" do
subject.should_receive(:system).with('tar -czf #path bar.tar.gz')
subject.create
end
end
【讨论】:
是的,我也有单元测试来测试方法等等。我的问题是我希望我的集成测试测试较少的实现,因为我正在单元测试中测试该实现。我的问题是关于如何 /not/ 在我的集成测试中测试实现。以上是关于Ruby 测试期望运行一个命令的主要内容,如果未能解决你的问题,请参考以下文章