48

我有一个 ASP.net 网站项目 (.net 3.5)。目前所有非代码隐藏在代码文件(包括 Linq2Sql 的东西、数据上下文、业务逻辑、扩展方法等)都位于 App_Code 文件夹中。

我有兴趣在项目的至少某些部分中引入单元测试(使用 nunit)。我将要进行的任何单元测试都需要对当前位于 App_Code 文件夹中的所有代码具有完全访问权限。到目前为止,我已经做了一些初步阅读,共识似乎是:

  • 鉴于我目前的设置,这将是不可能的
  • 单元测试需要引用作为已编译 dll 一部分的类,并且根据定义,网站项目仅在运行时编译。
  • 为了继续,我需要将整个项目转换为 Web 应用程序,或者将我想要测试的所有代码(即:App_Code 的全部内容)移动到类库项目并引用类库网站项目中的项目。其中任何一个都将提供对我需要的已编译 dll 格式的类的访问,这将允许我对它们进行单元测试。

它是否正确?还是有另一种方法可以在不重组/重构整个项目的情况下进行单元测试?

4

8 回答 8

24

我的商店终于为我们的 MVC 项目解决了这个问题。我想分享它,因为我在 StackOverflow 上追逐了很多死胡同,听到很多人说它无法完成。我们这样做:

  • 打开 MVC 文件夹“作为网站,来自本地 iis”,它可以让智能感知和调试正常工作
  • 添加一个单元测试项目,该项目位于我们的源代码控制目录中
  • 将预构建步骤添加到 TEST 项目,因为我们无法将一个预构建步骤添加到作为网站打开的项目中。假设网站是\FooSite,我们的测试项目是\FooSite.Tests。编译后的应用程序代码将在 FooSite.Tests\FooSite_Precompiled\bin 中结束。
  • *
<Target Name="BeforeBuild">
     <AspNetCompiler VirtualPath="FooSite" TargetPath="$(ProjectDir)\FooSite_Precompiled" Force="true"
 Debug="true" />   </Target>
  • 在您的测试项目中添加对 FooSite_Precompiled/bin/App_Code.dll 的引用。
  • 轰就是这样。你可以吃蛋糕也可以吃。每次在解决方案中单击 Build 时,您都会调用网站 csproj(仍然存在)上的 aspnet_compiler.ext 工具,与 MSBuild 不同,该工具能够编译 app_code,并且 Debug="true" 允许您进入 app_code。调试单元测试时的dll代码。而且您只需要在运行更新的单元测试时进行构建。当您查看更改对页面的影响时,您只需更改代码/保存/刷新页面,因为 app_code 文件夹在从 Web 服务器调用时会动态编译。
于 2012-04-30T15:43:46.973 回答
19

你的结论似乎是正确的。我会投票赞成将功能转移到一个或多个类库项目中,因为这也可能为在其他项目中重用相同的功能打开大门。

于 2009-07-29T07:38:32.533 回答
12

我们在我的公司有这个问题(我的老板不喜欢 DLL,关于版本控制的一些垃圾......)

我们有两种经常使用的方法:

1) 获取 CI 工具来进行单元测试:我们使用具有非常紧密的 NUnit 集成的 TeamCity,并且我们的解决方案构建速度足够快(并且测试足够少),因此这是一个有效的选项。

2) 手动预编译和单元测试生成的二进制文件:完全可以从命令行运行 ASP.net 编译器/MSBuild(就像您正在执行“发布”构建一样)并且只需对生成的二进制文件进行单元测试。

但是,如果您可以选择将代码分离为二进制文件(类库)或仅使用 Web 应用程序,我建议将其作为更好的选择。

于 2010-06-21T11:32:05.687 回答
6

如果有人发现自己正在实施 Brian 的解决方案,这里有一个 Website.targets 文件,您可以将其包含在单元测试解决方案中。它仅在 App_Code 更改时(重新)编译网站。只需添加类似

  <PropertyGroup>
    <WebsiteName>MyWebsite</WebsiteName>
    <WebsitePath>..</WebsitePath>
  </PropertyGroup>
  <Import Project="$(ProjectDir)\Website.targets" />
  <Target Name="BeforeBuild" DependsOnTargets="CompileWebsite">
  </Target>

到您的 .csproj,进行自定义WebsiteNameWebsitePath然后您应该准备好了。网站.目标:

<?xml version="1.0" encoding="utf-8"?>
<!--
    Target that compiles Website's App_Code to be used for testing
  -->
<Project DefaultTargets="CompileWebsite" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <AppCodeFiles Include="$(WebsitePath)\$(WebsiteName)\App_Code\**\*.*" />
  </ItemGroup>
  <Target Name="CompileWebsite" Inputs="@(AppCodeFiles)" Outputs="$(ProjectDir)\PrecompiledWeb\bin\App_Code.dll">
    <AspNetCompiler VirtualPath="$(WebsiteName)" PhysicalPath="$(WebsitePath)\$(WebsiteName)" TargetPath="$(ProjectDir)\PrecompiledWeb" Force="true" Debug="true" />
  </Target>
  <Target Name="CleanWebsite">
    <RemoveDir Directories="$(WebsitePath)\$(WebsiteName)\PrecompiledWeb" />
  </Target>  
</Project>
于 2013-06-04T08:17:32.590 回答
2

看起来这在仍然使用App_code时是可能的,但正如 Fredrik 和 Colin 建议的那样,我要么将此逻辑移出到它自己的类库项目中,要么将项目类型更改为 Web 应用程序。

我总是将自己的 ASP.NET 项目创建为 Web 应用程序项目而不是网站。

于 2009-07-29T08:06:54.487 回答
1

正如 OP 所说,也可以转移到 Web App 项目,我想说这也更干净,您的页面可以保留在 wep app 项目中,您将它们放在 1 个 DLL(可测试)中。您所有的业务逻辑等都在一个单独的类库中。

于 2009-07-29T08:00:06.343 回答
0

可以对存储在 App_Code 文件夹中的类进行单元测试,而无需将您的项目转换为 Web 应用程序或将您的类移动到类库项目中。

只需将代码文件的构建操作设置为编译。这将导致调试和单元测试您的网站输出一个 .dll 文件。

现在,当您从单元测试项目中引用您的网站项目时,app_code 文件夹中的类将可见。

笔记:

将您的 .cs 文件设置Build ActionCompile将导致您的网站在调试和单元测试时生成一个 .dll 文件。.dll 文件会在您调试网站时引起问题,因为 IIS 现在会在 bin 和 App_Code 文件夹这两个地方找到您的代码,并且不知道该使用哪一个。我目前只是在想调试时删除 .dll 文件。

于 2016-05-26T21:06:55.013 回答
0

我不得不通过添加PhysicalPath属性来更改 Brian White 的解决方案。此外,我没有使用Default Web Site并且不得不将VirtualPath属性更改为我的网站名称。

<Target Name="BeforeBuild">
    <AspNetCompiler VirtualPath="myIISsitename.com" PhysicalPath="$(SolutionDir)MySiteFolder" TargetPath="$(ProjectDir)\MySite_Precompiled" Force="true" Debug="true" />
</Target>

生成的 dll 将位于MySite_Precompiled\App_Code.dll

于 2016-07-19T01:11:00.570 回答