dotnet/roslyn-sdk

Exception inside CodeRefactoringTest: Sequence contains no elements

bjornhellander opened this issue · 2 comments

Hi!

I am experiencing a problem when writing unit tests for a code refactoring provider. I am trying to setup the test state slightly differently compared to how it is done in the project template. See lines marked with "NEW" below:

    public static partial class CSharpCodeRefactoringVerifier<TCodeRefactoring>
        where TCodeRefactoring : CodeRefactoringProvider, new()
    {
        public class Test : CSharpCodeRefactoringTest<TCodeRefactoring, MSTestVerifier>
        {
            public Test()
            {
                SolutionTransforms.Add((solution, projectId) =>
                {
                    var compilationOptions = solution.GetProject(projectId).CompilationOptions;
                    compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(
                        compilationOptions.SpecificDiagnosticOptions.SetItems(CSharpVerifierHelper.NullableWarnings));
                    solution = solution.WithProjectCompilationOptions(projectId, compilationOptions);
                    var documentId = solution.GetProject(projectId).DocumentIds.Single(); // NEW LINE !!!!!!!!!!!!!!!
                    solution = solution.WithDocumentFilePath(documentId, "x\\y.cs"); // NEW LINE !!!!!!!!!!!!!!!
                    return solution;
                });
            }
        }
    }

When I run a refactoring unit test using this test setup, I get an exception inside the CodeRefactoringTest class.
I have uploaded an example solution which reproduces the problem: https://github.com/bjornhellander/RefactoringTestProblem1.git
The repo contains two commits. The test passes on the first, but fails on the second. The change between those two is essentially the lines marked with "NEW" above.

Result when running the test:

 TestMethod1
   Source: UnitTests.cs line 13
   Duration: 1,8 sec

  Message: 
Test method RefactoringTestProblem1.Test.MyUnitTest.TestMethod1 threw exception: 
System.InvalidOperationException: Sequence contains no elements

  Stack Trace: 
ThrowHelper.ThrowNoElementsException()
Enumerable.Single[TSource](IEnumerable`1 source)
ImmutableArrayExtensions.Single[T](ImmutableArray`1 immutableArray)
<<ApplyRefactoringAsync>g__GetTriggerLocationAsync|0>d.MoveNext() line 308
--- End of stack trace from previous location ---
CodeRefactoringTest`1.ApplyRefactoringAsync(DiagnosticResult triggerSpan, ImmutableArray`1 codeRefactoringProviders, Nullable`1 codeActionIndex, String codeActionEquivalenceKey, Action`2 codeActionVerifier, Project project, Int32 numberOfIterations, IVerifier verifier, CancellationToken cancellationToken) line 249
CodeRefactoringTest`1.VerifyRefactoringAsync(String language, DiagnosticResult triggerSpan, ImmutableArray`1 codeRefactoringProviders, SolutionState oldState, SolutionState newState, Int32 numberOfIterations, Func`10 getFixedProject, IVerifier verifier, CancellationToken cancellationToken) line 157
CodeRefactoringTest`1.VerifyRefactoringAsync(SolutionState testState, SolutionState fixedState, DiagnosticResult triggerSpan, IVerifier verifier, CancellationToken cancellationToken) line 139
CodeRefactoringTest`1.RunImplAsync(CancellationToken cancellationToken) line 87
AnalyzerTest`1.RunAsync(CancellationToken cancellationToken) line 181
CSharpCodeRefactoringVerifier`1.VerifyRefactoringAsync(String source, DiagnosticResult[] expected, String fixedSource) line 33
CSharpCodeRefactoringVerifier`1.VerifyRefactoringAsync(String source, String fixedSource) line 14
MyUnitTest.TestMethod1() line 17
ThreadOperations.ExecuteWithAbortSafety(Action action)

I have looked at the sdk code and GetTriggerLocationAsync does indeed call Single() when trying to retrieve the test document, but why my test document would be gone at that point is beyond me. The tested refactoring provider (which is empty in the provided repo) does not get called at all in the second commit. Could you have a look and see if I have done something strange in the test setup or if there is a problem in the sdk code?

Using version 1.1.1 of Microsoft.CodeAnalysis.CSharp.CodeRefactoring.Testing.MSTest.

The full form allows setting the document path for each source file:

await new VerifyCS.Test
{
  TestState =
  {
    Sources =
    {
      ("/0/y.cs", content),
    }
  }
}.RunAsync();

Ok. Doing it that way instead, then :-) Thank you!