Unit Testing ASP.net Web Site Project code stored in App_Code

假装没事ソ 提交于 2019-11-27 06:48:01

Your conclusions seem correct. I would vote for moving functionality into one or several class library projects, since that may open the door for reusing the same functionality in other projects as well.

My shop has finally worked through an answer for this for our MVC project. And I want to share it as I chased a lot of dead ends here on StackOverflow hearing a lot of people say it couldn't be done. We do it like this:

  • Open the MVC folder "as a website, from local iis" which gets intellisense and debugging working properly
  • Add a unit test project that lives in our source controlled directory
  • Add a pre-build step to the TEST project, since we can't add one to a project that is open as a website. Imagine website is \FooSite and our test project is \FooSite.Tests. The compiled app code will end up in FooSite.Tests\FooSite_Precompiled\bin.
  • *
<Target Name="BeforeBuild">
     <AspNetCompiler VirtualPath="FooSite" TargetPath="$(ProjectDir)\FooSite_Precompiled" Force="true"
 Debug="true" />   </Target>
  • Add a reference to the FooSite_Precompiled/bin/App_Code.dll in your test project.
  • Boom that's it. You can have your cake and eat it too. Every time you click Build in your solution you call the aspnet_compiler.ext tool on your website csproj (which does still exist) which is able, unlike MSBuild, to compile app_code, and the Debug="true" allows you step into the app_code.dll code when debugging your unit test. And you only need to Build when you're running updated unit tests. When you're looking at the effects of your change on the page, you just Change Code/Save/Refresh Page since the app_code folder dynamically compiles when called from your web server.

We have this issue at my company (My boss doesn't like DLLs, some rubbish about versioning...)

We have two ways round it that we use frequently:

1) Get the CI tool to do the unit testing: We use TeamCity which has a pretty tight NUnit integration, and our solution builds quick enough (and has few enough tests) for this to be a valid option.

2) Manually precompile and unit test the resulting binaries: It's perfectly possible to run the ASP.net compiler / MSBuild from the command line (as if you were doing a 'Publish' build) and just unit test the resulting binaries.

However, if you have the option of segregating the code into binaries (class libraries) or just using a web application, I'd suggest that as a better alternative.

Should anyone find themselves implementing Brian's solution, here's a Website.targets file you can include in unit testing solution. It (re)compiles website only when App_Code changes. Just add something like

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

to your .csproj, customizing WebsiteName and WebsitePath and you should be ready to go. Website.targets:

<?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>

It looks like this is possible whilst still using App_code, but I would either move this logic out to its own class library project or change the project type to Web Application, as Fredrik and Colin suggest.

I always create my own ASP.NET projects as Web Application projects not Websites.

And as the OP stated it's also possible to move to a Web App project, which i would say is cleaner as well, your pages can stay in the wep app project, you will have them in 1 DLL (testable). All your business logic etc. goes in a separate class library / libraries.

It is possible to unit test classes stored in the App_Code folder without converting your project to a Web App or moving your classes to a Class Library project.

All that is necessary is setting the code files' Build Actions to Compile. This will cause Debugging and Unit Testing your website to output a .dll file.

Now when you reference your website project from the unit test project, the classes in the app_code folder will be visible.

NOTE:

Setting your .cs files' Build Action to Compile will cause your website to generate a .dll file on debugging and unit-testing. The .dll file will cause problems when you debug your website because IIS will now find your code in two places, the bin and the App_Code folder and will not know which one to use. I currently just delete the .dll file when I want to debug.

I had to change Brian White's solution by adding the PhysicalPath attribute. In addition I am not using the Default Web Site and had to change the VirtualPath property to my website name.

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

The resulting dll will be at MySite_Precompiled\App_Code.dll

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!