If, when running tests, you reference a resource using the pack://application: URI syntax
(regardless whether this reference is in the test code or in the actual application code)
you'll probably get this exception: "System.UriFormatException: Invalid URI: Invalid port specified."
There is information about this on the web, but the two easiest solutions aren't that easy to find
(they're there, just buried in longer discussions). Here, I give a short description of the problem,
description of solutions that won't help you (well, at least didn't help me), and the two quick solutions.
If you want to see those - just skip to the end.
Sometimes, when testing a class, I need to access a resource in the class's assembly (so, not in the current test assembly).
This is either done in the test code or in the class code. Something like this:
<TestMethod()>
Public Sub TestImage()
Const assembly As String = "Framework.Tests"
Const imagePath As String = "Cancel.png"
Const resourcePath As String =
"pack://application:,,,/" & assembly & ";component/Images/" & imagePath
Dim bitmapSource As New BitmapImage(New Uri(resourcePath))
. . .
End Sub
Doesn't have to be an image, just any kind of resource accessed using the 'pack://application:' URI.
Now, it's not a problem if this is part of your normal (non-test) code and you're running the application.
Usually, if you got the paths correctly, this works without problems; the problems start when you try to write 'unit' tests for this.
If you try to run the test code above, you'll get the error:
System.UriFormatException: Invalid URI: Invalid port specified.
The problem here is with 'pack:' not being recognized by the URI resolution engine.
Some texts on the web suggest that it should be enough to register handling of 'pack:' URIs;
there are various ways of doing that (read the MSDN documentation here, for instance).
But the problem is, that at least in the case above, 'pack:' registration doesn't really help:
<TestMethod()>
Public Sub TestImage()
Const assembly As String = "Framework.Tests"
Const imagePath As String = "Cancel.png"
Const resourcePath As String =
"pack://application:,,,/" & assembly & ";component/Images/" & imagePath
UriParser.Register(New GenericUriParser(
GenericUriParserOptions.GenericAuthority), "pack", -1)
' OR:
Dim uriSchemePack As String = PackUriHelper.UriSchemePack
' OR other methods...
Dim bitmapSource As New BitmapImage(New Uri(resourcePath))
. . .
End Sub
You'll still get an error (albeit a different one):
System.NotSupportedException: The URI prefix is not recognized.
Ah, ok, 'pack:' is now recognized, but the 'application:' handling part isn't...
Can't really find code that shows how pack/application URI handling should be registered.
Fortunately, the fact that the code doesn't throw exceptions during normal application runs, suggests other solutions.
Either of the two instructions below will 'force' full pack://application: package handling initialization:
Like so:
<TestMethod()>
Public Sub TestImage()
Const assembly As String = "Framework.Tests"
Const imagePath As String = "Cancel.png"
Const resourcePath As String =
"pack://application:,,,/" & assembly & ";component/Images/" & imagePath
Dim frameworkElement As New FrameworkElement
' OR
Dim application As Application = Application.Current
' This is the WPF Application (System.Windows.Application), not the WinForms one!
Dim bitmapSource As New BitmapImage(New Uri(resourcePath))
. . .
End Sub
(I actually like the second one a bit more; but probably this doesn't really matter...)
Anyway, the code above was added to the test method itself; but it's enough to initialize pack/application URI handling once... for the whole test run.
But, because sometimes you'll want to execute only one or two tests out of the whole suite,
I usually add this code to all test classes that need it, in the ClassInitialize method - doesn't hurt, but makes testing during development a bit easier.
HTH
Top
|