class ObservableDictMutationTests(unittest.TestCase): def setUp(self): self.od = ObservableDict({ 1: 'Crash', 2: 'Coco', 3: 'Pura', 4: 'Tiny Tiger' }) self.empty = ObservableDict() def test_ObservableDict_get_method_returns_appropriately(self): # arrange & act va11 = self.od.get(1) val2 = self.od.get(5) va13 = self.od.get(5, 'Dingo') # assert self.assertEqual(len(self.od), 4) self.assertTrue(va11 == 'Crash') self.assertIsNone(val2) self.assertIsNotNone(va13) self.assertEqual(va13, 'Dingo') def test_ObservableDict_get_with_index_access(self): # arrange val1 = self.od[1] # act & assert self.assertEqual(val1, 'Crash') with self.assertRaises(KeyError): # noinspection PyUnusedLocal value = self.od[5] def test_ObservableDict_del_a_value_or_entire_dict(self): # arrange & act del self.od[2] # assert self.assertEqual(len(self.od), 3) self.assertIsNone(self.od.get(2)) def test_ObservableDict_items_returns_items_as_key_value_pair(self): # arrange & act items = self.od.items() # assert self.assertIsNotNone(items) self.assertEqual(len(items), 4) def test_ObservableDict_del_deletes_entire_dictionary_and_calls_dispose( self): # arrange local_dict = ObservableDict({1: 'hello', 2: 'world'}) # act del local_dict # assert with self.assertRaises(UnboundLocalError): self.assertIsNone(local_dict) def test_ObservableDict_pop_removes_the_items_with_key_specified_and_returns_its_value( self): # arrange & act val1 = self.od.pop(4) val2 = self.od.pop(5, 'Dr. Neo Cortex') # assert self.assertEqual(len(self.od), 3) self.assertEqual(val1, 'Tiny Tiger') self.assertEqual(val2, 'Dr. Neo Cortex') def test_ObservableDict_popitem_removes_random_value(self): # arrange & act val1 = self.od.popitem() # assert self.assertIsNotNone(val1) self.assertEqual(len(self.od), 3) def test_ObservableDict_set_default_does_nothing_when_key_exists(self): # arrange & act val1 = self.od.setdefault(1) val2 = self.od.setdefault(2, 'Dingo') # assert self.assertIsNotNone(val1) self.assertEqual(val1, 'Crash') self.assertIsNotNone(val2) self.assertEqual(val2, 'Coco') def test_ObservableDict_set_default_creates_new_key_if_not_exists(self): # arrange & act val1 = self.od.setdefault(5, 'Dingo') val2 = self.od.setdefault(6) # assert self.assertIsNotNone(val1) self.assertEqual(val1, 'Dingo') self.assertIsNone(val2) def test_ObservableDict_fromkeys_creates_new_ObservableDict(self): # arrange & act new_dict = ObservableDict.fromkeys({1, 2, 3, 4, 5}) # assert self.assertIsNotNone(new_dict) self.assertTrue(isinstance(new_dict, ObservableDict)) self.assertEqual(len(new_dict), 5) def test_ObservableDict_clear_removes_all_items_in_dictionary(self): # arrange & act self.od.clear() # assert self.assertIsNotNone(self.od) self.assertEqual(len(self.od), 0) def tearDown(self): self.od.dispose() self.empty.dispose()
class RxNotificationObservableDictTest(unittest.TestCase): def setUp(self): self.od = ObservableDict({1: 'Crash', 2: 'Coco', 3: 'Pura', 4: 'Tiny'}) self.scheduler = TestScheduler() def test_ObservableDict_elements_deleted_with_del_keyword(self): # arrange obs = self.scheduler.create_observer() expected_message = [on_next(0, 2)] self.od.when_collection_changes() \ .map(lambda x: x.Items) \ .subscribe(obs) # act del self.od[2] # assert self.assertEqual(obs.messages, expected_message) self.assertEqual(len(self.od), 3) self.assertIsNone(self.od.get(2)) def test_ObservableDict_del_keyword_with_invalid_key(self): # arrange obs = self.scheduler.create_observer() expected_error = [on_error(0, KeyError(5))] self.od.when_collection_changes() \ .map(lambda x: x.Items) \ .subscribe(obs) # act del self.od[5] # assert self.assertEqual(obs.messages, expected_error) def test_ObservableDict_pop_with_invalid_key(self): # arrange obs = self.scheduler.create_observer() expected_message = [on_next(0, 'Coco'), on_error(0, KeyError(5))] self.od.when_collection_changes() \ .map(lambda x: x.Items) \ .subscribe(obs) # act self.od.pop(2) self.od.pop(5) self.od.pop(3) # assert self.assertEqual(obs.messages, expected_message) self.assertEqual(len(self.od), 2) # TODO: Re-visit here to see if this is valid. ??? def test_ObservableDict_popitem_removes_arbitrary_value(self): # arrange obs = self.scheduler.create_observer() self.od.when_collection_changes() \ .map(lambda x: x.Items) \ .subscribe(obs) # act self.od.popitem() self.od.popitem() # assert self.assertEqual(len(self.od), 2) self.assertEqual(len(obs.messages), 2) def test_ObservableDict_popitem_in_empty_dict_pushes_KeyError_in_on_error( self): # arrange obs = self.scheduler.create_observer() empty = ObservableDict() expected_error = [ on_error(0, KeyError('popitem(): dictionary is empty')) ] empty.when_collection_changes() \ .map(lambda x: x.Items) \ .subscribe(obs) # act empty.popitem() # assert self.assertEqual(obs.messages, expected_error) def test_ObservableDict_test_default_adds_key_if_not_exists(self): # arrange obs = self.scheduler.create_observer() self.od.when_collection_changes() \ .subscribe(obs) # act self.od.setdefault(5, 'Dingo') self.od.setdefault(6) # assert self.assertEqual(len(self.od), 6) self.assertEqual(len(obs.messages), 2) self.assertEqual(obs.messages[0].value.value.Items, 'Dingo') self.assertEqual(obs.messages[0].value.value.Action, CollectionChangeAction.ADD) self.assertEqual(obs.messages[1].value.value.Items, ()) self.assertEqual(obs.messages[1].value.value.Action, CollectionChangeAction.ADD) def test_ObservableDict_test_default_does_nothing_key_if_exists(self): # arrange obs = self.scheduler.create_observer() expected_message = [] self.od.when_collection_changes() \ .map(lambda x: x.Items) \ .subscribe(obs) # act self.od.setdefault(2, 'Dingo') self.od.setdefault(1) # assert self.assertEqual(len(self.od), 4) self.assertEqual(len(obs.messages), 0) self.assertEqual(obs.messages, expected_message) def test_ObservableDict_update_method_updates_existing_dictionary(self): # arrange obs = self.scheduler.create_observer() expected_values = ['Polar', 'Dingo'] self.od.when_collection_changes() \ .map(lambda x: x.Items) \ .subscribe(obs) # act self.od.update(ObservableDict({2: 'Polar', 5: 'Dingo'})) # assert self.assertEqual(len(self.od), 5) self.assertEqual(self.od.get(2), 'Polar') self.assertTrue(isinstance(obs.messages[0].value.value, ObservableDict)) self.assertEqual(list(obs.messages[0].value.value._dict.values()), expected_values) def test_ObservableDict_clear_removes_all_items_and_publish_clear_event( self): # arrange obs = self.scheduler.create_observer() self.od.when_collection_changes() \ .subscribe(obs) # act self.od.clear() # assert self.assertEqual(len(self.od), 0) self.assertEqual(len(obs.messages), 1) self.assertEqual(obs.messages[0].value.value.Items, ()) self.assertEqual(obs.messages[0].value.value.Action, CollectionChangeAction.CLEAR) def test_ObservableSet_with_any_operation_after_dispose_throws_DisposedException( self): # arrange obs = self.scheduler.create_observer() new_dict = ObservableDict({6: 'Polar', 5: 'Dingo'}) new_dict.when_collection_changes() \ .map(lambda x: x.Items) \ .subscribe(obs) # act & assert new_dict.dispose() with self.assertRaises(DisposedException): new_dict.setdefault(6) def tearDown(self): self.od.dispose()