title: Verify that task is being awaited
body: <p>I have the following code which i'd like to test:</p>
  
  <pre><code>private Task _keepAliveTask; // get's assigned by object initializer
  
  public async Task EndSession()
  {
      _cancellationTokenSource.Cancel(); // cancels the _keepAliveTask
      await _logOutCommand.LogOutIfPossible();
      await _keepAliveTask;
  }
  </code></pre>
  
  <p>It is important that the <code>EndSession</code> Task only ends once the `_keepAliveTask' ended. However, I'm struggling to find a way to test it reliably.</p>
  
  <p><strong>Question:</strong> How do i unit test the <code>EndSession</code> method and verify that the <code>Task</code> returned by <code>EndSession</code> awaits the <code>_keepAliveTask</code>.</p>
  
  <p>For demonstration purposes, the unit test could look like that:</p>
  
  <pre><code>public async Task EndSession_MustWaitForKeepAliveTaskToEnd()
  {
      var keepAliveTask = new Mock&lt;Task&gt;();
      // for simplicity sake i slightly differ from the other examples
      // by passing the task as method parameter
  
      await EndSession(keepAliveTask);
  
      keepAliveTask.VerifyAwaited(); // this is what i want to achieve
  }
  </code></pre>
  
  <p>Further criterias:
   - reliable test (always passes when implementation is correct, always fails when implementation is wrong)
   - cannot take longer than a few milliseconds (it's a unit test, after all).</p>
  
  <hr>
  
  <p><em>I have already taken several alternatives into considerations which i'm documenting below:</em></p>
  
  <h2>non-<code>async</code> method</h2>
  
  <p>If there wouldn't be the call to _logOutCommand.LogOutIfPossible() it would be quite simple: i'd just remove the <code>async</code> and <code>return _keepAliveTask</code> instead of <code>await</code>ing it:</p>
  
  <pre><code>public Task EndSession()
  {
      _cancellationTokenSource.Cancel();
      return _keepAliveTask;
  }
  </code></pre>
  
  <p>The unit test would look (simplified):</p>
  
  <pre><code>public void EndSession_MustWaitForKeepAliveTaskToEnd()
  {
      var keepAliveTask = new Mock&lt;Task&gt;();
      // for simplicity sake i slightly differ from the other examples
      // by passing the task as method parameter
  
      Task returnedTask = EndSession(keepAliveTask);
  
      returnedTask.Should().be(keepAliveTask);
  }
  </code></pre>
  
  <p>However, there's two arguments against this:</p>
  
  <ul>
  <li>i have multiple task which need awaiting (i'm considering <code>Task.WhenAll</code> further down)</li>
  <li>doing so only moves the responsibility to await the task to the caller of <code>EndSession</code>. Still will have to test it there.</li>
  </ul>
  
  <h2>non-async method, sync over async</h2>
  
  <p>Of course, I could do something similar:</p>
  
  <pre><code>public Task EndSession()
  {
      _cancellationTokenSource.Cancel(); // cancels the _keepAliveTask
      _logOutCommand.LogOutIfPossible().Wait();
      return _keepAliveTask;
  }
  </code></pre>
  
  <p>But that is a no-go (sync over async). Plus it still has the problems of the previous approach.</p>
  
  <h2>non-<code>async</code> method using <code>Task.WhenAll(...)</code></h2>
  
  <p>Is a (valid) performance improvement but introduces more complexity:
   - difficult to get right without hiding a second exception (when both fail)
   - allows parallel execution </p>
  
  <p>Since performance isn't key here i'd like to avoid the extra complexity. Also, previously mentioned issue that it just moves the (verification) problem to the caller of the <code>EndSession</code> method applies here, too.</p>
  
  <h2>observing effects instead of verifying calls</h2>
  
  <p>Now of course instead of "unit" testing method calls etc. I could always observe effects. Which is: As long as <code>_keepAliveTask</code> hasn't ended the <code>EndSession</code> <code>Task</code> mustn't end either. But since I can't wait indefinite one has to settle for a timeout. The tests should be fast so a timeout like 5 seconds is a no go. So what I've done is:</p>
  
  <pre><code>[Test]
  public void EndSession_MustWaitForKeepAliveTaskToEnd()
  {
      var keepAlive = new TaskCompletionSource&lt;bool&gt;();
      _cancelableLoopingTaskFactory
          .Setup(x =&gt; x.Start(It.IsAny&lt;ICancelableLoopStep&gt;(), It.IsAny&lt;CancellationToken&gt;()))
          .Returns(keepAlive.Task);
  
      _testee.StartSendingKeepAlive();
  
      _testee.EndSession()
              .Wait(TimeSpan.FromMilliseconds(20))
              .Should().BeFalse();
  }
  </code></pre>
  
  <p>But I really really dislike this approach:</p>
  
  <ul>
  <li>hard to understand</li>
  <li><strong>unreliable</strong></li>
  <li>or - when it's <em>quite</em> reliable - it takes a long time (which unit tests shouldn't).</li>
  </ul>