Ejemplo n.º 1
0
 def setUp(self) -> None:
     super(TestCandidateService, self).setUp()
     # Mocking the whole database is not unit testing but we don't care because this is done to only to
     # make target's initialization easier
     Mongo().db = mongomock.database.Database(mongomock.MongoClient(),
                                              'elections',
                                              _store=None)
     # Now we override whatever the DB would answer
     candidate1 = Candidate(**{'screen_name': 'sn1', 'nickname': 'n1'})
     candidate2 = Candidate(**{'screen_name': 'sn2', 'nickname': 'n2'})
     CandidateService().candidates = [candidate1, candidate2]
     # Get the object
     self.target = CandidateService()
Ejemplo n.º 2
0
 def test_update_followers_for_candidate_ok(self, store_mock, new_mock, previous_mock):
     twitter = MagicMock()
     candidate = Candidate(**{'screen_name': 'test'})
     FollowerUpdateService.update_followers_for_candidate(twitter, candidate)
     assert store_mock.call_count == 1
     assert new_mock.call_count == 1
     assert previous_mock.call_count == 1
Ejemplo n.º 3
0
 def find(self, screen_name):
     """ Get user with given screen name. """
     as_dict = self.get_first({'_id': screen_name})
     if as_dict is None:
         raise NonExistentCandidateError(screen_name)
     # Transform from DB format to DTO format
     as_dict['screen_name'] = as_dict['_id']
     return Candidate(**as_dict)
Ejemplo n.º 4
0
 def all(self):
     """ Get all currently stored candidates. """
     candidates = []
     as_dict_list = self.get_all()
     for as_dict in as_dict_list:
         # Transform from DB format to DTO format
         as_dict['screen_name'] = as_dict['_id']
         candidates.append(Candidate(**as_dict))
     return candidates
Ejemplo n.º 5
0
 def test_get_new_followers_ids(self, request_mock, retrieve_mock):
     twitter = MagicMock()
     candidate = Candidate(**{'screen_name': 'test'})
     followers_ids = ['123', '456', '789']
     # Do test
     new_followers = FollowerUpdateService.get_new_followers_ids(twitter, candidate, followers_ids)
     assert retrieve_mock.call_count == 2
     assert request_mock.call_count == 2  # Once outside the while, once inside of it
     assert len(new_followers) == 4
     assert new_followers == {'12', '324', '678', '55'}
Ejemplo n.º 6
0
 def test_update_followers_for_candidate_integration(self, store_mock, previous_mock, time_mock, continue_mock):
     twitter = MagicMock()
     twitter.get_followers_ids.side_effect = FollowerUpdateHelper.mock_get_followers_ids_with_exception
     candidate = Candidate(**{'screen_name': 'test'})
     FollowerUpdateService.update_followers_for_candidate(twitter, candidate)
     assert store_mock.call_count == 1
     assert previous_mock.call_count == 1
     assert time_mock.call_count == 1
     assert twitter.get_followers_ids.call_count == 3
     assert continue_mock.call_count == 2
Ejemplo n.º 7
0
 def add_candidate(self, screen_name, nickname=None):
     """ Add a candidate with given screen name and nickname to the database and to the json file. """
     try:
         CandidateDAO().find(screen_name)
     except NonExistentCandidateError:
         self.logger.info(f'Adding candidate {screen_name} to database.')
         candidate = Candidate(**{
             'screen_name': screen_name,
             'nickname': nickname
         })
         # Store in database
         CandidateDAO().save(candidate)
         # Update json resource
         CandidateDAO().update_json_resource(candidate)
         # Update current structure
         self.candidates.append(candidate)
         return
     raise CandidateAlreadyExistsError(screen_name)
Ejemplo n.º 8
0
class TestFollowerUpdateService(CustomTestCase):

    def setUp(self) -> None:
        super(TestFollowerUpdateService, self).setUp()
        # We need this to avoid mocking some object creations
        Mongo().db = mongomock.database.Database(mongomock.MongoClient(), 'elections', _store=None)
        FollowerUpdateHelper.restart_all_iterations()

    @mock.patch.object(CredentialService, 'get_all_credentials_for_service', return_value={})
    @mock.patch.object(AsyncThreadPoolExecutor, 'run')
    def test_update_followers_ok(self, async_mock, credentials_mock):
        FollowerUpdateService.update_followers()
        assert credentials_mock.call_count == 1
        assert async_mock.call_count == 1

    @mock.patch.object(CredentialService, 'get_all_credentials_for_service',
                       **{'side_effect': CredentialsAlreadyInUseError('test')})
    @mock.patch.object(AsyncThreadPoolExecutor, 'run')
    def test_update_followers_credentials_exception(self, async_mock, credentials_mock):
        FollowerUpdateService.update_followers()
        assert credentials_mock.call_count == 1
        assert async_mock.call_count == 0

    @mock.patch.object(FollowerUpdateService, 'twitter', return_value={})
    @mock.patch.object(FollowerUpdateService, 'next_candidate', side_effect=FollowerUpdateHelper.mock_next_candidate)
    @mock.patch.object(FollowerUpdateService, 'update_followers_for_candidate')
    @mock.patch.object(CandidateService, 'finish_follower_updating')
    @mock.patch.object(CredentialService, 'unlock_credential')
    def test_update_with_credential_ok(self, unlock_mock, finish_mock, update_mock, next_mock, twitter_mock):
        credential = Credential(**{'ID': 'test', 'CONSUMER_KEY': 'test', 'CONSUMER_SECRET': 'test'})
        FollowerUpdateService.update_with_credential(credential)
        assert unlock_mock.call_count == 1
        assert finish_mock.call_count == 1
        assert update_mock.call_count == 1
        assert next_mock.call_count == 2
        assert twitter_mock.call_count == 1

    @mock.patch.object(FollowerUpdateService, 'twitter', return_value={})
    @mock.patch.object(FollowerUpdateService, 'next_candidate', side_effect=FollowerUpdateHelper.mock_next_candidate)
    @mock.patch.object(FollowerUpdateService, 'update_followers_for_candidate')
    @mock.patch.object(CandidateService, 'finish_follower_updating')
    @mock.patch.object(CredentialService, 'unlock_credential')
    def test_update_with_credential_no_candidates(self, unlock_mock, finish_mock, update_mock, next_mock, twitter_mock):
        FollowerUpdateHelper.ITERATIONS = 0
        credential = Credential(**{'ID': 'test', 'CONSUMER_KEY': 'test', 'CONSUMER_SECRET': 'test'})
        FollowerUpdateService.update_with_credential(credential)
        assert unlock_mock.call_count == 1
        assert finish_mock.call_count == 0
        assert update_mock.call_count == 0
        assert next_mock.call_count == 1
        assert twitter_mock.call_count == 1

    @mock.patch.object(RawFollowerDAO, 'get_candidate_followers_ids', return_value=[])
    @mock.patch.object(FollowerUpdateService, 'get_new_followers_ids', return_value=[])
    @mock.patch.object(FollowerUpdateService, 'store_new_followers')
    def test_update_followers_for_candidate_ok(self, store_mock, new_mock, previous_mock):
        twitter = MagicMock()
        candidate = Candidate(**{'screen_name': 'test'})
        FollowerUpdateService.update_followers_for_candidate(twitter, candidate)
        assert store_mock.call_count == 1
        assert new_mock.call_count == 1
        assert previous_mock.call_count == 1

    @mock.patch.object(FollowerUpdateService, 'should_retrieve_more_followers',
                       side_effect=FollowerUpdateHelper.mock_should_retrieve)
    @mock.patch.object(FollowerUpdateService, 'do_request', side_effect=FollowerUpdateHelper.mock_do_request)
    def test_get_new_followers_ids(self, request_mock, retrieve_mock):
        twitter = MagicMock()
        candidate = Candidate(**{'screen_name': 'test'})
        followers_ids = ['123', '456', '789']
        # Do test
        new_followers = FollowerUpdateService.get_new_followers_ids(twitter, candidate, followers_ids)
        assert retrieve_mock.call_count == 2
        assert request_mock.call_count == 2  # Once outside the while, once inside of it
        assert len(new_followers) == 4
        assert new_followers == {'12', '324', '678', '55'}

    @mock.patch.object(RawFollowerDAO, 'put')
    @mock.patch.object(CandidatesFollowersDAO, 'put_increase_for_candidate')
    def test_store_new_followers(self, increase_mock, put_mock):
        FollowerUpdateService.store_new_followers({'012', '324', '678', '055'}, 'test-name')
        assert put_mock.call_count == 4
        assert increase_mock.call_count == 1

    @mock.patch.object(ConfigurationManager, 'get_int', return_value=2)
    def test_should_retrieve_more_followers_true(self, get_mock):
        result = FollowerUpdateService.should_retrieve_more_followers({'012', '234', '463'}, {'012', '532', '987'})
        assert result
        assert get_mock.call_count == 1

    @mock.patch.object(ConfigurationManager, 'get_int', return_value=2)
    def test_should_retrieve_more_followers_false(self, get_mock):
        result = FollowerUpdateService.should_retrieve_more_followers({'012', '234', '463'}, {'012', '234', '987'})
        assert not result
        assert get_mock.call_count == 1

    @mock.patch.object(CandidateService, 'get_for_follower_updating', return_value=Candidate(**{'screen_name': 'test'}))
    def test_next_candidate_ok(self, get_mock):
        candidate = FollowerUpdateService.next_candidate()
        assert candidate is not None
        assert candidate.screen_name == 'test'
        assert get_mock.call_count == 1

    @mock.patch.object(CandidateService, 'get_for_follower_updating',
                       **{'side_effect': FollowerUpdatingNotNecessaryError()})
    def test_next_candidate_no_more_candidates_to_update(self, get_mock):
        candidate = FollowerUpdateService.next_candidate()
        assert candidate is None
        assert get_mock.call_count == 1

    @mock.patch('time.sleep', return_value=None)
    def test_do_request_ok(self, time_mock):
        twitter = MagicMock()
        twitter.get_followers_ids.side_effect = FollowerUpdateHelper.mock_get_followers_ids
        response = FollowerUpdateService.do_request(twitter, 'test', 0)
        assert response is not None
        assert response == {'ids': [12, 324], 'next_cursor': 678}
        assert twitter.get_followers_ids.call_count == 1
        assert time_mock.call_count == 0

    @mock.patch('time.sleep', return_value=None)
    def test_do_request_with_exception(self, time_mock):
        twitter = MagicMock()
        twitter.get_followers_ids.side_effect = FollowerUpdateHelper.mock_get_followers_ids_with_exception
        response = FollowerUpdateService.do_request(twitter, 'test', 0)
        assert response is not None
        assert response == {'ids': [12, 324], 'next_cursor': 678}
        assert twitter.get_followers_ids.call_count == 2
        assert time_mock.call_count == 1

    @mock.patch.object(FollowerUpdateService, 'should_retrieve_more_followers',
                       side_effect=FollowerUpdateHelper.mock_should_retrieve)
    @mock.patch('time.sleep', return_value=None)
    @mock.patch.object(RawFollowerDAO, 'get_candidate_followers_ids', return_value=[])
    @mock.patch.object(FollowerUpdateService, 'store_new_followers')
    def test_update_followers_for_candidate_integration(self, store_mock, previous_mock, time_mock, continue_mock):
        twitter = MagicMock()
        twitter.get_followers_ids.side_effect = FollowerUpdateHelper.mock_get_followers_ids_with_exception
        candidate = Candidate(**{'screen_name': 'test'})
        FollowerUpdateService.update_followers_for_candidate(twitter, candidate)
        assert store_mock.call_count == 1
        assert previous_mock.call_count == 1
        assert time_mock.call_count == 1
        assert twitter.get_followers_ids.call_count == 3
        assert continue_mock.call_count == 2
Ejemplo n.º 9
0
 def mock_next_candidate():
     """ Returns a candidate NEXT_CANDIDATE_ITERATIONS times. Then, it returns None. """
     if FollowerUpdateHelper.NEXT_CANDIDATE_ITERATION >= FollowerUpdateHelper.ITERATIONS:
         return None
     FollowerUpdateHelper.NEXT_CANDIDATE_ITERATION += 1
     return Candidate(**{'screen_name': 'test'})