title: Test that a consumer method can raise an exception with Django Channels and pytest-asyncio
body: <p>Using Django and Channels 2, I have a consumer method that can can be accessed through channel groups and that may raise exceptions. Like this trivial one:</p>
  
  <pre class="lang-py prettyprint-override"><code>from channels.generic.websocket import WebsocketConsumer
  from asgiref.sync import async_to_sync
  
  class DummyConsumer(WebsocketConsumer):
      def connect(self):
          async_to_sync(self.channel_layer.group_add)(
              "dummy",
              self.channel_name,
          )
          self.accept()
  
      def will_raise(self, event):
          raise ValueError('value error')
  
      def disconnect(self, code):
          async_to_sync(self.channel_layer.group_discard)(
              "dummy",
              self.channel_name,
          )
  </code></pre>
  
  <p>I want to test this method using pytest-asyncio. Since one can catch the exception of a coroutine with <code>pytest.raises</code>, I thought naively that something like this would be enough:</p>
  
  <pre class="lang-py prettyprint-override"><code>import pytest
  from channels.testing import WebsocketCommunicator
  from channels.layers import get_channel_layer
  from app.consumers import DummyConsumer
  channel_layer = get_channel_layer()
  
  @pytest.fixture
  async def communicator():
      communicator = WebsocketCommunicator(DummyConsumer, "ws/dummy/")
      await communicator.connect()
      yield communicator
      await communicator.disconnect()
  
  @pytest.mark.asyncio
  async def test_will_raise(communicator):
      with pytest.raises(ValueError):
          await channel_layer.group_send('dummy', {
              'type': 'will_raise'
          })
  </code></pre>
  
  <p>But the test fails in a pretty confusing way (truncated output):</p>
  
  <pre class="lang-none prettyprint-override"><code>================== ERRORS ==================
  ___ ERROR at teardown of test_will_raise ___
  ...
  &gt;       raise ValueError('value error')
  E       ValueError: value error
  
  app/consumers.py:28: ValueError
  ================= FAILURES =================
  _____________ test_will_raise ______________
  ...
              await channel_layer.group_send('dummy', {
  &gt;               'type': 'will_raise'
              })
  E           Failed: DID NOT RAISE &lt;class 'ValueError'&gt;
  
  app/tests_dummy.py:21: Failed
  ==== 1 failed, 1 error in 1.47 seconds =====
  </code></pre>
  
  <p>So, what should I do? Is the raising of an exception from a consumer method a bad design?</p>