'Assert that a signal was sent with the correct arguments. Since
Django calls signal handlers with the signal as an argument,
it is added to `kwargs`.
Uses `mock.patch.object`, which requires the target to be
specified as a module along with a variable name inside that
module.
Args:
module (module): The module in which to patch the given signal name.
signal (str): The name of the signal to patch.
*args, **kwargs: The arguments which should have been passed
along with the signal. If `exclude_args` is passed as a
keyword argument, its value should be a list of keyword
arguments passed to the signal whose values should be
ignored.'

@contextmanager
def assert_signal_sent(self, module, signal, *args, **kwargs):

    with patch.object(module, signal, new=Signal()) as mock_signal:
        def handler(*args, **kwargs):
            'No-op    signal    handler.'
            pass
        mock_handler = Mock(spec=handler)
        mock_signal.connect(mock_handler)
        (yield)
        self.assertTrue(mock_handler.called)
        (mock_args, mock_kwargs) = mock_handler.call_args
        if ('exclude_args' in kwargs):
            for key in kwargs['exclude_args']:
                self.assertIn(key, mock_kwargs)
                del mock_kwargs[key]
            del kwargs['exclude_args']
        self.assertEqual(mock_args, args)
        self.assertEqual(mock_kwargs, dict(kwargs, signal=mock_signal))
