关于C#:如何对ASP.NET核心控制器或模型对象进行单元测试?

How do you unit test an ASP.NET Core controller or model object?

我正在尝试在Visual Studio 2015中使用ASP.NET Core MVC(在预览期间为ASP.NET 5,现在称为ASP.NET Core)应用程序获取一些控制器、模型和存储库(数据访问)C类。

我有以下结构:

1
2
3
4
5
6
7
   Solution
       |
      src
       |
       |-- ITConsole       <- main app (ASP.NET MVC, DNX 4.5.1)
       |
       `-- ITConsoleTests  <- What kind of project should this be?

main app使用的是dnx 4.5.1,但如果我创建一个标准的nunit单元测试应用程序,它只能作为一个经典的.NET框架类库提供,目标是.NET框架4.5.2,而不是作为一个可以与我的主应用程序一起使用的Web类库。

因此,为了避免它可能作为经典的.NET框架Microsoft单元测试框架项目(.NET程序集)工作,我尝试手动查找和添加引用(通过添加引用和浏览)以获得要解决的.NET依赖项。我知道.NET程序集引用很遗憾是不可传递的。因此,如果unittest.dll引用了mainapp.dll,而mainapp.dll依赖于ASP.NET MVC以及它所依赖的其他一切,那么我必须自己做。这就是我要做的。我在我的单元测试项目中添加了对C:\dev\Demo\ITConsole\artifacts\bin\ITConsole\Debug\dnx451\ITConsole.dll的引用,这样我就可以开始编译代码了。单元测试类会编译,但不会运行,这可能是因为尝试添加对ASP.NET的引用时遇到了麻烦。

现在,即使我添加了对common.logging.core和common.logging的引用,当我在测试资源管理器上单击"全部运行"时,也会出现以下错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Test Name:  TestStudyLogReadDocument
Test FullName:  ITConsoleTests.ITConsoleTestStudyLog.TestStudyLogReadDocument
Test Source:    C:\dev\Demo\ITConsole\ITConsoleTests\ITConsoleTestStudyLog.cs : line 52
Test Outcome:   Failed
Test Duration:  0:00:00.0712058

Result StackTrace:  
at Couchbase.Configuration.Client.ClientConfiguration..ctor()
   at ITConsole.Repository.StudyLogRepository..ctor() in C:\dev\Demo\ITConsole\src\ITConsole
epository\StudyLogRepository.cs:line 39
   at ITConsoleTests.ITConsoleTestStudyLog.SetupDb() in C:\dev\Demo\ITConsole\ITConsoleTests\ITConsoleTestStudyLog.cs:line 30
   at ITConsoleTests.ITConsoleTestStudyLog.TestStudyLogReadDocument() in C:\dev\Demo\ITConsole\ITConsoleTests\ITConsoleTestStudyLog.cs:line 53
Result Message:
Test method ITConsoleTests.ITConsoleTestStudyLog.TestStudyLogReadDocument threw exception:
System.IO.FileLoadException: Could not load file or assembly 'Common.Logging.Core, Version=3.1.0.0, Culture=neutral, PublicKeyToken=af08829b84f0328e' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

(在问这个问题时…)ASP.NET 5 MVC预览模板都不能为您生成单元测试。您甚至可以单元测试一个闪亮的新ASP.NET核心应用程序吗?请参见下面的屏幕截图,例如,在使用MSTEST的vs 2015中,如何开始单元测试的正常方法不可用。

no unit test for you


更新:Xunit仍然是一个好主意,但是这个答案现在已经过时了,因为如果您想使用ASP.NET核心,也可以使用"标准"MSTEST。(2016年6月1日)我觉得我还是喜欢Xunit,但这是你的电话。

最新的Xunit指令链接:Xunit wiki上提供了比此答案更新频率更高的优秀指令。

IDE解决方法:当Visual Studio变得愚蠢,无法"检测"并显示测试时,手动查找和删除%TEMP%\VisualStudioTestExplorerExtensions

截至2016年5月,随着ASP.NET核心1.0 RC1最近被RC2取代,似乎仍不可能使用标准的Microsoft单元测试框架和ASP.NET核心(以前称为ASP.NET 5),XUnit似乎是RC1和RC2的一个好选择。

您可以让xunit.net单元测试使用ASP.NET Core 1.0.0-RC1,使用Xunit Github项目的官方说明]2,该项目具有特定的".NET Core Getting Started"案例。

还可以安装XUnit新项目模板,该模板为常规的完整.NET和.NET核心提供模板化的单元测试项目。单击工具,然后在XUnit中单击扩展和更新类型,找到XUnit测试项目模板并安装该模板。不要安装任何XUnit测试运行程序,您不需要它。

我创建了一个工作示例并将其上载到bitback:

https://bitback.org/wpostma/aspnet5mvc6xUnitdemo

如果你没有mercurial,你可以从bitbacke下载一个zip。

演示包括一个通过的测试和一个失败的测试。

快速总结:

  • 您有Visual Studio 2015,其中包括Update2和"1.0.0预览"工具(最迟截至2016年5月)。

  • 创建Web类库,而不是单元测试项目。

  • 向它添加XUnit引用,并修复您的project.json(下面的示例)。

  • 写下你的课程(下面的例子)。

  • 使用测试资源管理器在IDE内部或外部运行测试,输入dnx . tests并检查输出(下面的示例)。

  • Project.json for 1.0.0-rc2,参考演示程序集和XUnit:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     {
     "version":"1.0.0-*",

     "testRunner":"xunit",

     "dependencies": {
       "Microsoft.NETCore.App": {
         "version":"1.0.0-rc2-3002702",
         "type":"platform"
        },

       "dotnet-test-xunit":"1.0.0-rc2-*",

       "xunit":"2.1.0",


       "YetAnotherWebbyDemo":"1.0.0-*"
      },

     "frameworks": {
       "netcoreapp1.0": {
         "imports": [
           "dotnet5.6",
           "dnxcore50",
           "portable-net45+win8"
          ]
        }
      }
    }

    单元测试类(无论什么.cs):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;

    using Xunit;

    using YetAnotherWebbyDemo.Models;

    namespace YetAnotherWebbyDemoTests
    {
        // This project can output the Class library as a NuGet Package.
        // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select"Produce outputs on build".
        public class TestBasics
        {
            [Fact]
            public void TestAdd()
            {

                TestableModelClass TestMe = new TestableModelClass();


                Assert.True(TestMe.Add(3, 2) == 5,"Basic Math Failure");

                Assert.True(TestMe.Add(-3, -2) == -5,"Basic Math Failure");
            }

        }
    }

    使用dnx时,rc1中命令行的输出示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    C:\dev\Demo\YetAnotherWebbyDemo\src\YetAnotherWebbyDemoTests>dnx . test

    xUnit.net DNX Runner (32-bit DNX 4.5.1)
      Discovering: YetAnotherWebbyDemoTests
      Discovered:  YetAnotherWebbyDemoTests
      Starting:    YetAnotherWebbyDemoTests
        YetAnotherWebbyDemoTests.TestBasics.TestAdd [FAIL]
          Basic Math Failure
          Expected: True
          Actual:   False
          Stack Trace:
            YetAnotherWebbyDemoTestBasics.cs(25,0): at YetAnotherWebbyDemoTests.Test
    Basics.TestAdd()
      Finished:    YetAnotherWebbyDemoTests
    === TEST EXECUTION SUMMARY ===
       YetAnotherWebbyDemoTests  Total: 1, Errors: 0, Failed: 1, Skipped: 0, Time: 0.263s

    RC2中使用dotnet的输出示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    D:\dev\aspnet5mvc6xunitdemo\src\YetAnotherWebbyDemoTests>dotnet test
    Project YetAnotherWebbyDemo (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
    Project YetAnotherWebbyDemoTests (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
    xUnit.net .NET CLI test runner (64-bit win10-x64)
      Discovering: YetAnotherWebbyDemoTests
      Discovered:  YetAnotherWebbyDemoTests
      Starting:    YetAnotherWebbyDemoTests
        YetAnotherWebbyDemoTests.TestBasics.TestAdd [FAIL]
          Basic Math Failure
          Expected: True
          Actual:   False
          Stack Trace:
            D:\dev\aspnet5mvc6xunitdemo\src\YetAnotherWebbyDemoTests\YetAnotherWebbyDemoTestBasics.cs(26,0): at YetAnotherWebbyDemoTests.TestBasics.TestAdd()
      Finished:    YetAnotherWebbyDemoTests
    === TEST EXECUTION SUMMARY ===
       YetAnotherWebbyDemoTests  Total: 1, Errors: 0, Failed: 1, Skipped: 0, Time: 0.205s
    SUMMARY: Total: 1 targets, Passed: 0, Failed: 1.


    Xunit团队在更新文档方面做得很好。

    为了始终更新信息,请参阅XUnit文档:

    http://xunit.github.io/docs/getting-started-dotnet-core.html


    随着RC2的发布,XUnit集成不再适用于我的项目(现在已经修复了,请参阅注释)。为了能够测试我的项目,我转向了Nunit。它似乎支持RC2,并且有一个轻量级的测试运行程序nunitlite。

    基本上,你需要将NunitLite托管到一个控制台应用程序中,并用"dotnet run"启动它。

    添加以下依赖项:

    1
    2
    3
    "dependencies": {
    "NUnit":"3.2.1",
    "NUnitLite":"3.2.1",

    要启动测试运行程序,需要将此代码添加到program.cs文件中:

    1
    2
    3
    4
    5
    6
    7
    public class Program
    {
        public static void Main(string[] args)
        {
            new AutoRun().Execute(args);
        }
    }