Problems with DeploymentItem attribute

六眼飞鱼酱① 提交于 2019-11-27 17:39:17
Martin Peck

DeploymentItem is a bit of a mess.

Each file in your solution will have a "Copy To Output Folder" setting in VS.NET. You need this to be "Copy Always" (or similar) in order to get the files into the output folder.

Check that you've got this set for the new files. If you don't have this set then the files won't get copied to the output folder, and then they can't be deployed from the output folder to the folder where MSTest does it stuff.

Personally, if I have files that I need for my unit tests I've found that embedding those files as resources into an assembly, and having that assembly "unpack" itself during the tests is a more predictable way of doing things. YMMV.

note: These comments are based upon my experience with VS2010. Comments to my answer would suggest that this is not problem with VS2012. I still stand by comments that using embedded resources involves less "magic" and, for me, makes the "arrange" stage of my unit tests much more explicit.

In VS2010, my Local.testsettings had the "Enable Deployment" unchecked and the DeploymentItem attribute was not working. I checked it and everything worked fine. I hope this helps!

Murari Kumar

I have also faced similar problems but i found easy 3 step solution for this:

Assuming your folder structure looks like this: SolutionFolder\ TestProjectFolder\ SubFolder\

  1. Go to "Solutions Items/Local.testsettings" > "Deployment" > Check "Enable Deployment"
  2. If you are using VS2010, make sure any files you want to deploy have their "Copy To Output Folder" property set to "Copy Always" or "Copy if Newer"
  3. Attribute your TestMethod with either one of:
    • [DeploymentItem(@"TestProjectFolder\SubFolder")] to deploy all contents of <SubFolder> to the Test Run directory
    • [DeploymentItem(@"TestProjectFolder\SubFolder", "TargetFolder")] to deploy all contents of <SubFolder> to <TargetFolder> in the Test Run directory

One final note about MSTest (at least for VS2010):

If you want the <TargetFolder> to have the same name as the <SubFolder>, using [DeploymentItem(@"SubFolder", @"SubFolder")] will fail silently as the MSTest runner hits a silly edge case. This is why you should prefix the <SubFolder> with the <TestProjectFolder> as so: [DeploymentItem(@"TestProjectFolder\SubFolder", @"SubFolder")]

Peter K.

For hopefully helping someone else out: I tried all the suggestions here and still my deployment item was not being copied.

What I had to do (as suggested here) was to add a second parameter to the DeploymentItem attribute:

[DeploymentItem(@"UnitTestData\TestData.xml", "UnitTestData")]

If you go into your .testrunconfig file and under deployment uncheck "Enable Deployment", the tests will run in their normal location, and everything will work like it does when running the app outside a unit test.

This probably doesn't relate to your exact problem, but here's a couple of tips I found with the [DeploymentItem] attribute.

  1. Copy to output directory should be set to Copy Always.

It does NOT work when used with the [TestInitialize] attribute

[TestInitialize]
[DeploymentItem("test.xlsx")]
public void Setup()
{

It should be on your [TestMethod], e.g.

    [TestInitialize]
    public void Setup()
    {
        string spreadsheet = Path.GetFullPath("test.xlsx");
        Assert.IsTrue(File.Exists(spreadsheet));
        ...
    }

    [TestMethod]
    [DeploymentItem("test.xlsx")]
    public void ExcelQuestionParser_Reads_XmlElements()
    {
        ...
    }

After trying all of the other suggestions listed here I still couldn't figure out what was going on. Finally I discovered that there was no settings file selected under Test/Test Settings menu, which meant that Deployment wasn't being enabled. I clicked the Test/Test Settings/Select Test Settings File menu item, selected the Local.TestSettings file, then everything worked.

user1546704

Not sure if this exactly answers the question, but it may help some. First, I've found the "Enable Deployment" box must be checked for deployment to work. Second, the doc says the source path is "relative to the project path" which at first I took to mean the project folder. In fact, it seems to refer to the build output folder. So if I have a project folder called 'TestFiles' and a file in it called Testdata.xml, using the attribute this way doesn't work:

[DeploymentItem(@"TestFiles\Testdata.xml")] 

I can mark the Testdata.xml file Copy Always, so that the build puts a copy under the output folder (e.g., Debug\TestFiles\TestData.xml). The deployment mechanism will then find the copy of the file located at that path (TestFiles\Testdata.xml) relative to the build output. Or, I can set the attribute this way:

[DeploymentItem(@"..\\..\TestFiles\Testdata.xml")] 

and the deployment mechanism will find the original file. So either works, but I have noticed that using the Copy Always I occasionally run into the same problem I have when editing the app.config file in a project - if I don't change code or force a rebuild, nothing triggers copying of files marked to be copied on build.

I had Deployment flag disabled first. But even after I enabled it, for some unknown reason nothing even target DLLs would still be copied. Accidentally I opened Test Run window and killed all the previous runs and magically I found all the DLLs and files I needed in the test folder the very next run... Very confusing.

I was having huge problems trying to get files to deploy - trying all the suggestions above.

Then I closed VS2010; restarted it, loaded the solution and everything worked. (!)

I did some checking; After setting the 'Enable deployment' flag on local.TestSetting you should not simply re-run the test from the Test Results window. You have to get the previous test run removed from the UI e.g. by running a different test, or by re-opening your solution.

Since I always found the DeploymentItem attribute a mess, I do the deployment of such files by using the post-build script. - Make sure the files you wanna copy has the Copy Always property set. - Modify your test project post-build script to copy the files from build target folder(Bin\Debug) to the location where your test is expecting them.

Patrik Lindström

Try this for VS2010. So you do not need to add DeployItems for every tif
Remove the

[DeploymentItem(@"files\valid\valid_entries.txt")]  
[DeploymentItem(@"files\tif\")]  

Add a test configuration.
- right-click on solution node in solution explorer
- Add -> New Item...
- Select Test Settings node on the left, select the item on the right
- Click Add

Call it eg TDD

Choose TDD under TestMenu > Edit Testsettings.

Click on the Deployment. Enable it and then Add the files and directories that you want.There will be a path relative to the solution. The files will be put on. The original file are for example here:

D:\Users\Patrik\Documents\Visual Studio 2010\Projects\DCArrDate\WebMVCDCArrDate\Trunk\WebMVCDCArrDate\Authority.xml  

When I run my unit test it gets copied to

D:\Users\Patrik\Documents\Visual Studio 2010\Projects\DCArrDate\WebMVCDCArrDate\Trunk\WebMVCDCArrDate.Tests\bin\Debug\TestResults\Patrik_HERKULES 2011-12-17 18_03_27\Authority.xml  

in testcode I call it from:

[TestMethod()]
public void Read_AuthorityFiles_And_ParseXML_To_Make_Dictonary()  
{  
  string authorityFile = "Authority.xml";  
  var Xmldoc = XDocument.Load(authorityFile);  

There is no need to choose Copy Always; put the files in the testproject; add hardcoded paths in the testcode. For me this solution worked best. I tried with DeploymentItem, copy always but it was not to my liking.

I've been working on this in VS2013. My findings to get this working:

  • Copy to output directory should be set to Copy Always: MANDATORY.
  • "Enable Deployment" in .TestSettings: NOT REQUIRED. I got this working without a .TestSettings file at all.
  • Specifying a folder as 2nd parameter: OPTIONAL. Shapes the output folder layout, works fine without.
  • SPACES in the filename: this caused me a headache - the file was never copied. Removing the spaces fixed this. Haven't looked into escape characters yet.

A tip I also learned the hard way: do not forget to add this attribute to each individual test. The file copies on the first attributed test in the testrun, but remained missing when the order of the tests changed and non-attributed tests tried to find the file first.

Sudhanshu Mishra

For those who prefer to avoid the mess of DeploymentItem and take the approach suggested by @Martin Peck (accepted answer), you can use the following code to access the contents of the embedded resource:

public string GetEmbeddedResource(string fullyQulifiedResourceName)
{
    var assembly = Assembly.GetExecutingAssembly();
    // NOTE resourceName is of the format "Namespace.Class.File.extension";

    using (Stream stream = assembly.GetManifestResourceStream(fullyQulifiedResourceName))
    using (StreamReader reader = new StreamReader(stream))
    {
        string result = reader.ReadToEnd();
    }
}

For details, see this SO Thread

Jon Schneider

For me, the root cause was something else entirely: The production code being exercised by my tests was renaming and/or deleting the .xml test file being deployed.

Therefore, when I would run my tests individually, they'd pass, but when running them all together, the 2nd and subsequent test would fail with "file not found" errors (which I'd originally misdiagnosed as the DeploymentItem attribute not working).

My solution was to have each individual test method make a copy of the deployed file (using this technique), and then have the production code being tested use the copied file instead of the original.

We have spent a lot of time by Deployment items problem to solve it in local unittest run and teamcity unittest reun as well. It is not easy.

Very good tool to debug this issue is ProcessExplorer. Using process explorer, you can check where is Visual Studio searching for the deployment items and make the correction to the project. Just filter all file operation where path contains your deploymentitem filename and you will see it.

Pavenhimself

Besides the Deployment attribute needing to be checked, I discovered something else about the DeploymentItem attribute.

[TestMethod()]
[DeploymentItem("folder\subfolder\deploymentFile.txt")]
public void TestMethod1()
{
   ...
}

Your deploymentFile.txt needs to be relative to the solution file and not the testfile.cs.

My big "gotcha" was the way DeploymentItem handles directories. I was using the two-parameter version with both as directory path containing subdirectories I wanted deployed. I didn't realize initially that it only copies the stuff in the ROOT of the directory and not the entire recursive folder structure!

I basically had [DeploymentItem(@"Foo\", @"Foo\")] and was expecting it to deploy my Foo\Bar. I specifically had to change it to [DeploymentItem(@"Foo\Bar\", @"Foo\Bar\")] and now it works like a charm.

I have also faced similar problems. I have all the steps mentioned above but still no luck. I am using VS2010. Then i have found that $Menu > Test > Select Active Test Setting > Trace and Test impact was selected. It started working after i change Trace and test impact to Local. This page contains very resourceful information about copying files to test results folder, I feel to add this experience as well.

Don't use DeploymentItem.

It is very hard to set up correctly and it was not working with my ReSharper test runner nor the native one for MSTEST in Visual Studio 2017.

Instead, right click your data file, and select properties. Select Copy to output directory: Always.

Now in your test, do this. The directory is simply the directory of the file relative to the test project. Easy.

    [TestMethod()]
    public void ParseProductsTest()
    {
        // Arrange
        var file = @"Features\Products\Files\Workbook_2017.xlsx";
        var fileStream = File.Open(file, FileMode.Open);
        // etc.
    }

Caveat. I have no idea if this works well with automated build and test systems. I'm not there yet.

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