Mock function appends instead of replacing return values

35 views Asked by At

I'm writing a script that uses spotipy to just list albums of a specific artist. I'm trying to create a test for my script, by mocking the artist_albums function that should return a dict.

This is my script:

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'])
        
see_album('spotify:artist:2WX2uTcsvV5OnS0inACecP')

and this is my test

import unittest
from unittest.mock import Mock, patch
from spotify_playlist import see_album  # Replace 'your_module' with the actual name of your module

class TestSeeAlbum(unittest.TestCase):
    @patch('spotipy.Spotify')
    def test_see_album(self, mock_spotify):
        # Create a mock Spotify instance
        mock_spotify_instance = Mock()
        mock_spotify.return_value = mock_spotify_instance

        # Define the expected results from the mocked API
        mock_spotify_instance.artist_albums.return_value = {
            'items': [
                {'name': 'Album 1'},
                {'name': 'Album 2'},
                # Add more albums as needed
            ],
            'next': None  # No more pages
        }

        # Call the function
        see_album('spotify:artist:2WX2uTcsvV5OnS0inACecP')
 
        # Assert that the Spotify API methods were called correctly
        mock_spotify_instance.artist_albums.assert_called_once_with('spotify:artist:2WX2uTcsvV5OnS0inACecP', album_type='album')
        
        # Assert that the print statements in the function were called with the expected album names
        expected_output = [
            unittest.mock.call('Album 1'),
            unittest.mock.call('Album 2'),
            # Add more expected calls for additional albums
        ]
        self.assertEqual(
            mock_spotify_instance.artist_albums.call_args_list,
            expected_output
        )

if __name__ == '__main__':
    unittest.main()

I was expecting an output like this:

Album 1
Album 2

instead this is the full output:

Portraits (+ Remixes)
Portraits
Young Heart
Beautiful Lies (Deluxe)
Beautiful Lies
Fire Within (Deluxe)
Fire Within
Live in London
Birdy
Album 1
Album 2
F
======================================================================
FAIL: test_see_album (test_spotify.TestSeeAlbum)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.10/unittest/mock.py", line 1379, in patched
    return func(*newargs, **newkeywargs)
  File "/workspaces/hitparadeitalia-spotify/test_spotify.py", line 34, in test_see_album
    self.assertEqual(
AssertionError: [call('spotify:artist:2WX2uTcsvV5OnS0inACecP', album_type='album')] != [call('Album 1'), call('Album 2')]

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (failures=1)

So it looks like I'm able to append the items I want to return, but I'm not able to replace the existing ones, and the script does the actual call to the API, something I would like to avoid.

0

There are 0 answers