Python's assert_called_with, is there a wildcard character?
Question: Suppose I have a class in python set up like this.

    
    
    from somewhere import sendmail
    
    class MyClass:
    
        def __init__(self, **kargs):
            self.sendmail = kwargs.get("sendmail", sendmail)  #if we can't find it, use imported def
    
        def publish():
    
            #lots of irrelevant code
            #and then
    
            self.sendmail(mail_to, mail_from, subject, body, format= 'html')
    

So as you can see, I have sort of given myself the option to parameterize
which function I use for self.sendmail

Now in the test file.

    
    
    Class Tester():
    
        kwargs = {"sendmail": MagicMock(mail_from= None, mail_to= None, subject= None, body= None, format= None)}
        self.myclass = MyClass(**kwargs)
    
        ##later on
        def testDefaultEmailHeader():
    
            default_subject = "Hello World"
            self.myclass.publish()
    
            self.myclass.sendmail.assert_called()  #this is doing just fine
            self.myclass.sendmail.assert_called_with(default_subject)  #this is having issues
    

For some reason I am getting the error message

    
    
    AssertionError: Expected call: mock('Hello World')
                    Actual Call : mock('defaultmt', 'defaultmf', 'Hello World', 'default_body', format= 'html')
    

So basically, the assert is expecting sendmail to be called with only one
variable, when it ends up being called with all 5. The thing is, I don't care
about what the other 4 variables are! I just want to make sure it is called
with the correct subject.

I tried the mock place holder ANY, and got the same thing

    
    
    self.myclass.sendmail.assert_called_with(ANY, ANY, 'Hello World', ANY, ANY)
    
    AssertionError: Expected call: mock(<ANY>, <ANY>, 'Hello World', <ANY>, <ANY>)
    Actual Call : mock('defaultmt', 'defaultmf', 'Hello World', 'default_body, 'format= 'html') 
    

Really unsure on how to proceed with this one. Anyone have any advice if we
only care about one of the variable and want to ignore the rest?


Answer: If you're calling `sendmail` with a named parameter `subject` then it's better
to check whether the named argument matches what you expect:

    
    
    args, kwargs = self.myclass.sendmail.call_args
    self.assertEqual(kwargs['subject'], "Hello World")
    

This does assume both implementations of `sendmail` have a named parameter
called `subject`. If that's not the case you can do the same with a positional
parameter:

    
    
    args, kwargs = self.myclass.sendmail.call_args
    self.assertTrue("Hello World" in args)
    

You can be explicit about the position of the argument (i.e., the first
argument or the third argument that's passed to `sendmail` but that depends on
the implementation of `sendmail` being tested).

