我在使用外部api时遇到问题,下面是示例
require 'rspec'
require 'google/apis/storage_v1'
module Google
class Storage
def upload file
puts '#' * 90
puts "File #{file} is uploaded to google cloud"
end
end
end
class UploadWorker
include Sidekiq::Worker
def perform
Google::Storage.new.upload 'test.txt'
end
end
RSpec.describe UploadWorker do
it 'uploads to google cloud' do
google_cloud_instance = double(Google::Storage, insert_object: nil)
expect(google_cloud_instance).to receive(:upload)
worker = UploadWorker.new
worker.perform
end
end
我正在尝试对Google :: Storage类进行存根。此类在被测试的对象内实例化。如何验证此实例上的邮件期望?
在上面的示例中运行时,我得到以下输出,这似乎合乎逻辑,我的double值未被测试对象使用
(Double Google::Storage).upload(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
我是Rspec的新手,在此方面遇到困难,我们将不胜感激。
谢谢!
答案 0 :(得分:4)
达到DI始终是一个好主意(https://stackoverflow.com/a/51401376/299774),但有时由于某些原因您可能无法做到这一点,因此这是在不更改“生产”代码的情况下进行存根的另一种方法。
expect_any_instance_of
it 'uploads to google cloud' do
expect_any_instance_of(Google::Storage).to receive(:insert_object)
worker = UploadWorker.new
worker.perform
end
如果您只想测试该方法是否在任何此类对象上调用该方法。
如果您想控制或设置更多期望,可以这样做
it 'uploads to google cloud' do
the_double = instance_double(Google::Storage)
expect(Google::Storage).to receive(:new).and_return(the_double)
# + optional `.with` in case you wanna assert stuff passed to the constructor
expect(the_double).to receive(:insert_object)
worker = UploadWorker.new
worker.perform
end
再次-依赖注入更加清晰,您应该为此而努力。这是另一种可能性。
答案 1 :(得分:2)
我会考虑进行依赖注入,例如:
#import "PopUpViewController.h"
@interface PopUpViewController ()
@end
@implementation PopUpViewController
- (void)viewDidLoad {
self.view.backgroundColor=[[UIColor blackColor] colorWithAlphaComponent:.6];
self.popUpView.layer.cornerRadius = 5;
self.popUpView.layer.shadowOpacity = 0.8;
self.popUpView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
self.popUpView.clipsToBounds = YES;
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma animation
- (void)showAnimate
{
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3);
self.view.alpha = 0;
[UIView animateWithDuration:.25 animations:^{
self.view.alpha = 1;
self.view.transform = CGAffineTransformMakeScale(1, 1);
}];
}
- (void)removeAnimate
{
[UIView animateWithDuration:.25 animations:^{
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3);
self.view.alpha = 0.0;
} completion:^(BOOL finished) {
if (finished) {
[self.view removeFromSuperview];
}
}];
}
- (void)showInView:(UIView *)aView animated:(BOOL)animated
{
[aView addSubview:self.view];
if (animated) {
[self showAnimate];
}
}
- (IBAction)closePopup:(id)sender {
NSLog(@"closing...");
[self removeAnimate];
}
@end
然后您可以在规范中添加一个double:
class UploadWorker
def initialize(dependencies = {})
@storage = dependencies.fetch(:storage) { Google::Storage }
end
def perform
@storage.new.upload 'test.txt'
end
end
如果不是使用初始化程序,则可以使用getter / setter方法注入依赖项:
storage = double
expect(storage).to receive(...) # expection
worker = UploadWorker.new(storage: storage)
worker.perform
以及在规格中:
def storage=(new_storage)
@storage = new_storage
end
def storage
@storage ||= Google::Storage
end