Mock spotipy artist_albums未替换返回值却追加,测试调用实际API失败
问题修复方案
核心问题分析
你遇到的三个问题根源分别是:
- Mock路径错误,导致实际Spotify API被调用
- 断言逻辑错误,混淆了API调用记录与print输出的断言对象
- 脚本未做防护,测试时自动执行了实际函数调用
分步修复
1. 修复Mock路径,避免实际API调用
在测试代码中,@patch的目标应该是被测试模块中导入的spotipy.Spotify,而非库本身的类。假设你的脚本文件名为spotify_playlist.py,需把@patch('spotipy.Spotify')改为@patch('spotify_playlist.spotipy.Spotify')。
原因:Python的Mock基于模块导入引用工作,必须替换被测试代码实际使用的类实例,才能拦截API调用。
2. 修复断言逻辑,正确验证print输出
原测试错误地将artist_albums的调用记录与print调用做对比,需改为Mockprint函数,再断言它的调用参数。
3. 脚本添加执行防护,避免测试时自动运行
把原脚本中直接调用see_album的代码放到if __name__ == '__main__':块中,这样测试导入模块时不会执行实际调用。
修改后的完整代码
原脚本(spotify_playlist.py)
import spotipy from spotipy.oauth2 import SpotifyClientCredentials def see_album(birdy_uri): spotify = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials()) results = spotify.artist_albums(birdy_uri, album_type='album') albums = results['items'] while results['next']: results = spotify.next(results) albums.extend(results['items']) for album in albums: print(album['name']) # 添加执行防护,仅直接运行脚本时执行 if __name__ == '__main__': see_album('spotify:artist:2WX2uTcsvV5OnS0inACecP')
测试代码(test_spotify.py)
import unittest from unittest.mock import Mock, patch, call from spotify_playlist import see_album class TestSeeAlbum(unittest.TestCase): # 修正patch路径为被测试模块中的spotipy.Spotify @patch('spotify_playlist.spotipy.Spotify') # 同时Mock内置print函数,用于断言输出 @patch('builtins.print') def test_see_album(self, mock_print, mock_spotify): # 创建mock的Spotify实例 mock_spotify_instance = Mock() mock_spotify.return_value = mock_spotify_instance # 模拟artist_albums的返回值,无分页 mock_spotify_instance.artist_albums.return_value = { 'items': [ {'name': 'Album 1'}, {'name': 'Album 2'}, ], 'next': None } # 调用测试函数 see_album('spotify:artist:2WX2uTcsvV5OnS0inACecP') # 验证artist_albums的调用参数是否正确 mock_spotify_instance.artist_albums.assert_called_once_with( 'spotify:artist:2WX2uTcsvV5OnS0inACecP', album_type='album' ) # 验证print函数的调用是否符合预期 expected_print_calls = [ call('Album 1'), call('Album 2'), ] mock_print.assert_has_calls(expected_print_calls, any_order=False) if __name__ == '__main__': unittest.main()
验证结果
运行测试后,不会再调用实际Spotify API,测试会通过,且输出仅为测试框架的结果(无真实专辑列表与Mock专辑列表混合输出)。
内容的提问来源于stack exchange,提问作者LucaB
相关产品推荐
相关产品推荐

