testing.rst 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. .. _testing:
  2. How to Test
  3. ===========
  4. For testing purposes, it might be useful to prevent
  5. sending the actual email. This is especially preferable
  6. with unit tests. There are several ways to do this.
  7. .. note::
  8. Red Mail extends :stdlib:`email.message.EmailMessage <email.message.html#email.message.EmailMessage>`
  9. from standard library. You may use its attributes and
  10. methods for testing the contents of your messages.
  11. Using get_message
  12. -----------------
  13. All of the arguments in method :py:meth:`.EmailSender.send`
  14. are passed to :py:meth:`.EmailSender.get_message` method
  15. which generates the message itself. Therefore, the simplest
  16. solution is to use this method instead of :py:meth:`.EmailSender.send`
  17. in tests:
  18. .. code-block:: python
  19. from redmail import EmailSender
  20. # Just put something as host and port
  21. email = EmailSender(host="localhost", port=0)
  22. msg = email.get_message(
  23. subject='email subject',
  24. sender="me@example.com",
  25. receivers=['you@example.com'],
  26. text="Hi, this is an email.",
  27. )
  28. assert str(msg) == """from: me@example.com
  29. subject: Some news
  30. to: you@example.com
  31. Content-Type: text/plain; charset="utf-8"
  32. Content-Transfer-Encoding: 7bit
  33. MIME-Version: 1.0
  34. Hi, nice to meet you.
  35. """
  36. Mock Server
  37. -----------
  38. In case changing to method :py:meth:`.EmailSender.get_message`
  39. is inconvenient or it does not suit to your testing, you may
  40. also create a mock SMTP server that imitates an actual SMTP
  41. server instance:
  42. .. code-block:: python
  43. class MockSMTP:
  44. messages = []
  45. def __init__(self, host, port):
  46. self.host = host
  47. self.port = port
  48. def starttls(self):
  49. # Called only if use_startls is True
  50. return
  51. def login(self, username, password):
  52. # Log in to the server (if credentials passed)
  53. self.username = username
  54. self.password = password
  55. return
  56. def send_message(self, msg):
  57. # Instead of sending, we just store the message
  58. self.messages.append(msg)
  59. def quit(self):
  60. # Closing the connection
  61. return
  62. Then to use this mock:
  63. .. code-block:: python
  64. from redmail import EmailSender
  65. email = EmailSender(
  66. host="localhost",
  67. port=0,
  68. username="me@example.com",
  69. password="1234",
  70. cls_smtp=MockServer
  71. )
  72. email.send(
  73. subject='email subject',
  74. sender="me@example.com",
  75. receivers=['you@example.com'],
  76. text="Hi, this is an email.",
  77. )
  78. msgs = MockServer.messages
  79. assert msgs == ["""from: me@example.com
  80. subject: Some news
  81. to: you@example.com
  82. Content-Type: text/plain; charset="utf-8"
  83. Content-Transfer-Encoding: 7bit
  84. MIME-Version: 1.0
  85. Hi, nice to meet you.
  86. """]
  87. Note that an instance of ``MockServer`` is created
  88. for each connection, often per sent email.
  89. Subclass Sender
  90. ---------------
  91. Another option is to just subclass the sender and
  92. change the email sending there:
  93. .. code-block:: python
  94. from redmail import EmailSender
  95. class MockSender(EmailSender):
  96. def __init__(self, *args, **kwargs):
  97. super().__init__(*args, **kwargs)
  98. self.messages = []
  99. def send_message(self, msg):
  100. self.messages.append(msg)
  101. Then to use this class:
  102. .. code-block:: python
  103. # Just put something as host and port
  104. email = MockSender(host="localhost", port=0)
  105. email.send(
  106. subject='email subject',
  107. sender="me@example.com",
  108. receivers=['you@example.com'],
  109. text="Hi, this is an email.",
  110. )
  111. msgs = email.messages
  112. assert msgs == ["""from: me@example.com
  113. subject: Some news
  114. to: you@example.com
  115. Content-Type: text/plain; charset="utf-8"
  116. Content-Transfer-Encoding: 7bit
  117. MIME-Version: 1.0
  118. Hi, nice to meet you.
  119. """]