testfx icon indicating copy to clipboard operation
testfx copied to clipboard

Application.ResourceAssembly set to "testhost.x86" causing WPF Application test to fail

Open nietras opened this issue 4 years ago • 5 comments

Description

I am porting some code with unit tests from .NET Framework 4.7 to .NET 5.0. Both are using latest MSTest v2 as shown below.

    <PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
    <PackageReference Include="MSTest.TestFramework" Version="2.2.7" />

As part of these tests is a single test that spins up a WPF App : Application, this has been working fine in .NET Framework 4.7 by first setting:

Application.ResourceAssembly = typeof(Program).Assembly;

To ensure the ResourceAssembly is correctly defined as being the assembly where the App resides. This was possible in .NET Framework since the ResourceAssembly had not been set. But in .NET 5.0 ResourceAssembly is now pre-set to e.g. {testhost.x86, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}. This means we can no longer set it since you can only set it once.

System.InvalidOperationException: 'The 'ResourceAssembly' property of the 'Application' type cannot be changed after it has been set.'

Even using [ModuleInitializer] the ResourceAssembly is still pre-set, as can be seen with below.

        [ModuleInitializer]
        public static void Init()
        {
            var resourceAssembly = Application.ResourceAssembly;
            System.Diagnostics.Trace.WriteLine(resourceAssembly.FullName);
        }

I understand the issues around testing WPF application etc, but this has worked before and wondering what steps can be done to make it work again.

Steps to reproduce

  • Create a WPF application project
  • Create a MSTest v2 test project in same solution
  • Add reference to WPF application project in test project
  • Set TargetFrameworks to net47;net5.0-windows
  • Create unit test in that first sets Application.ResourceAssembly = typeof(Program).Assembly; and then tries creating the App and runs it
  • Then add any WPF resource and use the pack://application: format to refer to it.
Icon="pack://application:,,,/Resources/Application.ico"
  • .NET Framework run works, .NET 5.0 does not.

Expected behavior

Application.ResourceAssembly is null and can be overridden in test.

Actual behavior

Application.ResourceAssembly is set to testhost.x86 or similar.

Environment

  • Operating system: Windows 10 64-bit
  • Build version of vstest.console: Microsoft (R) Test Execution Command Line Tool Version 16.11.0
  • Package version of MSTest framework and adapter: See above

nietras avatar Sep 15 '21 08:09 nietras

I had the same problem. It might not be the solution you are looking for but i was able to work around it by explicitly specifying the local assembly as you would with a referenced assembly. Now i don't need to set the ResourceAssembly anymore.

I changed: Icon="pack://application:,,,/Resources/Application.ico"

To: Icon="pack://application:,,,/MyAssembly;component/Resources/Application.ico"

I hope this helps

MarcoScholten avatar Oct 01 '21 21:10 MarcoScholten

@MarcoScholten thanks, but no this would require us to "hard-code" all resources to specific assembly name, which I wanted to avoid.

nietras avatar Oct 08 '21 16:10 nietras

@haplois @jakubch1 still seeing this issue in .NET 6, how I can I resolve/fix this?

nietras avatar Nov 15 '21 10:11 nietras

Hi, a temporary workaround that worked for me is setting the resource assembly using reflection. Considering the implementation of Application.ResourceAssembly the following method accomplishes what the property setter does:


public static void SetResourceAssembly(Assembly assembly)
{  
    var _resourceAssemblyField = typeof(Application).GetField("_resourceAssembly", BindingFlags.Static | BindingFlags.NonPublic);
    if (_resourceAssemblyField != null)
        _resourceAssemblyField.SetValue(null, assembly);

    var resourceAssemblyProperty = typeof(BaseUriHelper).GetProperty("ResourceAssembly", BindingFlags.Static | BindingFlags.NonPublic);
    if (resourceAssemblyProperty != null)
        resourceAssemblyProperty.SetValue(null, assembly);
}

bemobolo avatar Feb 16 '22 14:02 bemobolo

@nietras @bemobolo Are you still facing this issue? If so, could you provide a full repro please?

Evangelink avatar Sep 06 '22 08:09 Evangelink

Closing this issue as there is no activity. Please feel free to open a new issue or comment if you are still facing issue.

Evangelink avatar Oct 13 '22 08:10 Evangelink

@Evangelink the issue is still there. Though I'm not sure it's related to MSTest. I've attached repro project. Tests.zip

mogikanin avatar Jan 20 '23 05:01 mogikanin

@mogikanin Your repro project references only NUnit so for sure it's not linked to MSTest. Please report an issue at NUnit if you feel like something is wrong.

Evangelink avatar Jan 20 '23 09:01 Evangelink

Dear @Evangelink, you simply could replace nunit with mstest, and you'll get the same issue. I used nunit because it's more comfortable for me. You already had clear steps to reproduce at initial description. My sample confirms this bug. Please spend some more time to deep into details.

mogikanin avatar Jan 20 '23 10:01 mogikanin