面试题答案
一键面试1. 初始化项目
首先,确保安装了 rspec
作为测试框架。如果没有安装,可以通过 gem install rspec
安装。
2. 创建 UserService
类文件
在项目目录下创建 user_service.rb
文件,内容如下:
class UserService
def initialize(database)
@database = database
end
def get_user_info(user_id)
# 这里的实现会在测试驱动下逐步完善
nil
end
end
3. 创建测试文件
在项目目录下创建 spec/user_service_spec.rb
文件,内容如下:
require 'rspec'
require_relative '../user_service'
describe UserService do
let(:database) { double('Database') }
let(:user_service) { UserService.new(database) }
describe '#get_user_info' do
let(:user_id) { 1 }
let(:user_data) { { name: 'John', age: 30 } }
it 'should return user info' do
allow(database).to receive(:fetch_user_data).with(user_id).and_return(user_data)
result = user_service.get_user_info(user_id)
expect(result).to eq(user_data)
end
end
end
4. 完善 UserService
类方法
回到 user_service.rb
文件,完善 get_user_info
方法:
class UserService
def initialize(database)
@database = database
end
def get_user_info(user_id)
@database.fetch_user_data(user_id)
end
end
5. 理由说明
- Mock/Stub技术:使用
double
创建了Database
类的模拟对象,通过allow(...).to receive(...).and_return(...)
来设置模拟对象的行为,这样避免了实际数据库调用,提高了测试的稳定性和速度,同时也解耦了UserService
与Database
类的直接依赖,使测试更聚焦于UserService
本身的逻辑。 - 测试覆盖率:目前的测试覆盖了
get_user_info
方法的主要逻辑路径,即调用Database
的fetch_user_data
方法并返回结果。如果UserService
类后续有更多复杂逻辑,如对返回数据的处理等,应相应增加测试用例,确保测试覆盖率达到80%以上。例如,如果get_user_info
方法在返回数据前对数据进行了过滤或格式化操作,就需要添加额外的测试用例来覆盖这些逻辑。