Unit-Testing of Private Async Methods with Visual Studio

Description

Given there is the need to unit-test a private async method. The class to be tested might look like this:

public ClassWithPrivateAsyncMethod
{

// Some stuff

  private async Task PrivateMethodAsync
    (
    string input
    )
  {
    // Call some async framework method
    var result = await SomeFrameworkMethodAsync(input);
    // do something with the result
  }

// Some more stuff

}

In former – pre VS 2012 – times, one would have right-clicked inside this method, selected “Create Private Accessor…” and “Create Unit Tests…”, and implemented the test. Well, this was then, and this is now. Nowadays, Visual Studio does not have the ability to create private accessors and unit test bodies.

But still, you are able to create a unit test yourself. And instead of having a private accessor, we can use Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject, which is included in %Program Files (x86)%\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll (path might vary slightly with version changes, this is the path for Visual Studio 2012). To use this assembly, I had to set the Copy Local property of the reference to true.

Instead of wring much more prose, here is the implementation of the unit test method:

using Mut = Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
// some other usings

[TestClass]
public ClassWithPrivateAsyncMethodTest
{
  [TestMethod]
  public async Task TestPrivateMethodAsync()
  {
    // Create an instance of the class to be tested.
    ClassWithPrivateAsyncMethod instance 
      = new ClassWithPrivateAsyncMethod();

    // Create a PrivateObject to access private methods of instance.
    Mut.PrivateObject privateObject 
      = new Mut.PrivateObject(instance);

    // Create parameter values
    object[] args = new object[] { "SomeValue" };

    // Call the method to be tested via reflection, 
    // pass the parameter, and await the return
    await (Task)privateObject.Invoke("PrivateMethodAsync", args);

    // Do some validation stuff
  }

// Some more stuff

}

Have a look at the checklist to be sure not to miss a detail.

Checklist

Check Combine async with return type Task in method declaration. Even if the method returns void, the declaration should be async Task. Otherwise, it cannot be awaited, what would lead to some trouble in testing the method.

Check Add reference to Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll in your test project. You have to browse for it. The assembly can be found in %Program Files (x86)%\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll (path might vary slightly with version changes, this is the path for Visual Studio 2012).

Check Set Copy Local to true for the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll reference.

Check Declare an alias for the Microsoft.VisualStudio.TestTools.UnitTesting namespace if you also use Microsoft.VisualStudio.TestPlatform.UnitTestFramework. This helps you to avoid using classes of the wrong namespace. There are some overlappings.

Check Declare testing method async Task, not async void. Otherwise, it will not be recognized as a test method, even when the TestMethodAttribute is set.

Check Use PrivateObject to access private methods of instances. It is located in the namespace Microsoft.VisualStudio.TestTools.UnitTesting.

Check Cast PrivateObject.Invoke‘s return value to Task to make sure the call can be awaited.

Check Await PrivateObject.Invoke. Otherwise, the tests in the testing method might be performed before the tested method returns.

Links

Async Return Types (C# and Visual Basic)

Handling of Out-Parameters with .NET Reflection

SCC Removal Tool for TFS / Visual Studio

Preface

Publishing sample code to the blog requires some manual tasks to remove all the source control configurations and files as well as the user specific files of Visual Studio.

After publishing a few code samples, having to do the same changes manually again and again, I thought it was time to create a tool doing this for me. Of course, taking the time I needed to build that tool, I could have published a few more code samples. But it is much more fun to write a tool than to do the same thing again and again 😉 And of course, having a tool makes sure I will not forget a step.

The primary intention is to disconnect the solution from source control. I don’t like samples downloaded from the internet where the first thing that happens is, that VS complains it cannot connect to the source control. Beside removing the SCC footprint, the tool also deletes all the output. I think the output is not needed when the source code is delivered.

This tool is created based on the usage of TFS 2012 und Visual Studio 2012. So maybe, when using older versions of VS or other version control systems, this tool might not remove all the SCC footprint.

SCC Files To Delete

TFS creates a .vssscc for each solution and a .vspscc file per project. The tool searches for these files in the working directory and its subdirectories and deletes them.

Disconnect From Source Control

The solution file .sln file contains some information about the source control system where the code is stored. All this is configured inside GlobalSection(TeamFoundationVersionControl). The whole section needs to be removed to disconnect the solution from source control.

The project file .csproj (suffix of C# projects) also contains some SCC footprint. Every line starting with >Scc needs to be removed too.

User Files To Delete

Visual Studio stores user-specific information related to the solution in .sou files. User-specific information related to the project are stored in .user files. The tool deletes all of these file types in the working directory and below.

Directories To Delete

By default, the output of a project is written to bin and obj directories, which are located below the project directory. All directories with these names are deleted. You can enter additional directory names in the “Remove Directories” field. I use this because I change the output for all configurations to “.\Output” by default.

And for those of you who create unit tests: the TestResults directories are included in the list of default directories too.

Configuration Abilities

The tool reads the default file types and directories to be deleted from the app.config. So in case you like to change these values, just edit the file. The tool also stores the values entered (working directory and additional directories to be removed) into the app.config.

The SCC footprint detection of the solution and project files is hard-coded. So in case you need some changes here, you have to change the code.

Maybe Incomplete

Yes, the tool might be not be complete. There are several reasons for this: C# is the preferred programming language in my company. So maybe some language-specific files or settings are not covered by the tool.

Also, we do create only a small subset of applications types, like WPF, Windows services, … So maybe SharePoint or Office projects look different. Again, if you need to cover these project types and the tool does not: you have the code, so change it.

Not To Be Forgotten

The software is provided “as is”, without warranty of any kind, expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non-infringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.

Be careful!

The source code can be found here.

SCC Remover Screenshot

Visual Studio UI Toolbox disappeared

I can’t recall if it was right after the initial installation, or if I hit any whatever key-combination to hide it, or closed it by mistake: The UI toolbox in my Visual Studio 2012 was not visible. First, I did not care because I didn’t needed it. But the point in time came when I needed it – and still it was not there. Neither a ‘Toolbox’ item in the View menu.

I searched the internet, did a repair, did a toolbox rebuild, reset the window layout, and was close to un- and reinstall it. Then, after searching again, I found a posting for VS 2008 SP1. It says one can use the CTRL+ALT+X key to show the toolbox window. Fortunately, the key combination worked for VS 2012 too! The toolbox window was back again 🙂 This saved me several hours of non-productive installation time.

Soon, I added the Toobox command to the ‘View / Other Windows’ menu to make sure I will not lose it again.

And in case you need to rebuild the toolbox content, you can do this:

1. Close Visual Studio;

2. Open the “c:\Users\\AppData\Local\Microsoft\VisualStudio\11.0″ folder and remove all the .TBD files;

3. Start regedit;

4. Find the “HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0\ToolboxControlsInstaller_AssemblyFoldersExCache” and “HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0\ToolboxControlsInstallerCache” keys;

5. Remove everything from these keys leaving them empty;

6. Run Visual Studio again and wait until it recreates all items in the toolbox. This might be a lazy rebuild, started when you open a UI control in the editor.

(found this list here: www.devexpress.com/Support/Center/Question/Details/K18560)

Limit Code Analysis Warnings

Visual Studio Code Analysis hat ein Limit von 200 für die Anzahl der Code-Analysis-Warnungen. Dies ist gut, um trotz der vielen Warnungen ein Projekt kompilieren zu können, kann aber auch ein Problem verursachen, wenn Tools eingebunden werden, welche selbst massive Anzahlen von Warnungen generieren und auf die Warnung von VS, dass dieses Limit überschritten sein, mit einem Abbruch reagieren. In meinem konkreten Fall ging es um DocProject, welches sinniger Weise mit einer “OutOfMemoryException” abbricht, wenn die Anzahl der undokumentierten Funktionen 200 übersteigt (sollte ja nicht vorkommen aber…). Wer also wissen möchte, wie viele CA-Warnungen er wirklich hat, sollte den Wert in der Registry erhöhen (die Änderung ist sofort wirksam).

Beschreibung von Microsoft: When first running Visual Studio Code Analysis over a large project, you may encounter the following error: CA0503: Additional warnings cannot be displayed. By default, a maximum of 200 warnings are displayed in the Error List. You can increase this amount by modifying the following registry value: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\Setup\EDev\CodeAnalysisErrorListViolationLimit Simply set this to a value that suits your needs.