我在ruby模型中有一个方法调用,如下所示:
$date = $date->format('Y-m-d')
在模型的spec.rb文件中,我试图模拟该调用并通过传入参数来获取值。但是我很难弄清楚调用它的正确方法。
在我的spec.rb文件顶部,有:
Contentful::PartnerCampaign.find_by(vanityUrl: referral_source).load.first
在describe块中,我尝试了以下操作:
let(:first_double) {
double("Contentful::Model", fields {:promotion_type => "Promotion 1"})
}
您可能会猜到,这些都不起作用。有人知道做这种事情的正确方法吗?甚至有可能吗?
答案 0 :(得分:2)
一般来讲,我不希望使用存根链,因为它们通常表示您违反了Law of Demeter。但是,如果需要的话,这就是我模拟该序列的方式:
class Report_item(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=255, help_text='*Title for the post e.g. item identity')
item_type = models.CharField(default="", max_length=100,
help_text='*Enter the item name you found e.g. Marksheet,key,wallet')
location = models.CharField(max_length=60, help_text='*Enter the address/street where you find this item')
city = models.CharField(max_length=60, help_text='*Enter the city name')
date = models.DateTimeField(default=timezone.now)
Description = models.TextField(blank=True,null=True,help_text='*Enter full description about item')
publish = models.BooleanField(default=False)
image = models.FileField(default="add Item image",
help_text='*Please uplocad a item image to identify by the owner')
def __str__(self):
return self.title + " " + str(self.publish)
def get_absolute_url(self):
return reverse('feed:detail', kwargs={'pk': self.pk})
class Meta:
ordering = ["-date"]
答案 1 :(得分:0)
我认为您需要像这样在两行中重构链:
model = double("Contentful::Model", fields: { promotion_type: "Promotion 1" })
campaign = double
allow(Contentful::PartnerCampaign).to receive(:find_by).with(vanityUrl: 'test_promo_path').and_return(campaign)
allow(campaign).to receive_message_chain(:load, :first).and_return(model)
然后,您可以编写将该属性传递给find_by
的规范,并检查链条。
答案 2 :(得分:0)
这就是我要做的。请注意,我将“模拟”部分和“期望”部分分开,因为通常我会在下面有其他一些it
示例(然后,我将需要那些it
示例)相同的“模拟”逻辑),并且因为我希望它们具有单独的关注点:it
示例中的任何内容通常都应该只专注于“预期”,因此,任何模拟或其他逻辑,我通常都会将它们放在it
之外。
let(:expected_referral_source) { 'test_promo_path' }
let(:contentful_model_double) { instance_double(Contentful::Model, promotion_type: 'Promotion 1') }
before(:each) do
# mock return values chain
# note that you are not "expecting" anything yet here
# you're just basically saying that: if Contentful::PartnerCampaign.find_by(vanityUrl: expected_referral_source).load.first is called, that it should return contentful_model_double
allow(Contentful::PartnerCampaign).to receive(:find_by).with(vanityUrl: expected_referral_source) do
double.tap do |find_by_returned_object|
allow(find_by_returned_object).to receive(:load) do
double.tap do |load_returned_object|
allow(load_returned_object).to receive(:first).and_return(contentful_model_double)
end
end
end
end
end
it 'calls Contentful::PartnerCampaign.find_by(vanityUrl: referral_source).load.first' do
expect(Contentful::PartnerCampaign).to receive(:find_by).once do |argument|
expect(argument).to eq({ vanityUrl: expected_referral_source})
double.tap do |find_by_returned_object|
expect(find_by_returned_object).to receive(:load).once do
double.tap do |load_returned_object|
expect(load_returned_object).to receive(:first).once
end
end
end
end
end
it 'does something...' do
# ...
end
it 'does some other thing...' do
# ...
end
如果您不了解ruby的tap
方法,请随时使用check this out