def test_commands_Set_run(monkeypatch, some_param_gr, patch_logging): pre_states = [State('pre')] post_states = [State('post')] @attr.s(auto_attribs=True) class SomeParamGroup(some_param_gr): attr3: str = inputs.ParamGroupInputBase._attr_ib( some_param_gr._param_group, default='' ) @attr3.validator def _check_attr3(self, attribute, value): if type(value) is not str: raise TypeError('attr3 should be str') set_cmd = commands.Set(SomeParamGroup, pre_states, post_states) input_param = SomeParamGroup('new-value1', 'new-value2') calls = [] apply_error = None post_apply_error = None # TODO consider to use mocks (e.g. pytest-mock plugin) @attr.s(auto_attribs=True) class PillarUpdater: targets: str = ALL_MINIONS def update(self, *args, **kwargs): calls.append((PillarUpdater.update, args, kwargs)) def apply(self, *args, **kwargs): nonlocal apply_error calls.append((PillarUpdater.apply, args, kwargs)) if apply_error: _error = apply_error apply_error = None raise _error def rollback(self, *args, **kwargs): calls.append((PillarUpdater.rollback, args, kwargs)) class StatesApplier: @staticmethod def apply(*args, **kwargs): nonlocal post_apply_error calls.append((StatesApplier.apply, args, kwargs)) if post_apply_error and args == (post_states,): _error = post_apply_error post_apply_error = None raise _error monkeypatch.setattr( commands, 'PillarUpdater', PillarUpdater ) monkeypatch.setattr( commands, 'StatesApplier', StatesApplier ) # dry run # performs validation with pytest.raises(TypeError) as excinfo: set_cmd.run(1, 2, 3, dry_run=True) assert str(excinfo.value) == 'attr3 should be str' assert not calls # performs validation set_cmd.run(input_param, dry_run=True) assert not calls # happy path set_cmd.run(input_param) assert calls == [ (PillarUpdater.update, (input_param,), {}), (StatesApplier.apply, (pre_states,), {}), (PillarUpdater.apply, (), {}), (StatesApplier.apply, (post_states,), {}), ] return # error during refresh calls[:] = [] apply_error = RuntimeError with pytest.raises(apply_error): set_cmd.run(input_param) assert calls == [ (PillarUpdater.update, (input_param,), {}), (StatesApplier.apply, (pre_states,), {}), (PillarUpdater.apply, (), {}), (PillarUpdater.rollback, (), {}), (PillarUpdater.apply, (), {}), (StatesApplier.apply, (post_states,), {}), ] # error during post apply calls[:] = [] apply_error = None post_apply_error = KeyError with pytest.raises(post_apply_error): set_cmd.run(input_param) assert calls == [ (PillarUpdater.update, (input_param,), {}), (StatesApplier.apply, (pre_states,), {}), (PillarUpdater.apply, (), {}), (StatesApplier.apply, (post_states,), {}), (PillarUpdater.rollback, (), {}), (PillarUpdater.apply, (), {}), (StatesApplier.apply, (post_states,), {}), ]