问题
I'm trying to write a unit test that will test a visual appearance of my custom control. Therefore I want to capture the control visual appearance using RenderTargetBitmap and then use assertions on result pixels. Here is my test:
[TestClass]
public class UnitTest2
{
[TestMethod]
public void TestMethod2()
{
//pixels to test
byte[] pixels = null;
// Since I create a UI elements, I need to use Dispatcher here.
var task = CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () =>
{
// Here I create a visual element that I want to test
var brush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));
var element = new Border()
{
MinWidth = 20,
MinHeight = 20,
Background = brush,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
BorderThickness = new Thickness(0)
};
// create an instance of RenderTargetBitmap to render a bitmap
var rtb = new RenderTargetBitmap();
var rtbTask = rtb.RenderAsync(element).AsTask();
// the following operation lasts for ages
// May be the reason is that the element is not a part of the VisualTree
rtbTask.Wait();
var rtbGetPixelsTask = rtb.GetPixelsAsync().AsTask<IBuffer>();
rtbGetPixelsTask.Wait();
pixels = rtbGetPixelsTask.Result.ToArray();
});
task.AsTask().Wait();
Assert.AreEqual<byte>(255, pixels[0]);
Assert.AreEqual<byte>(255, pixels[1]);
Assert.AreEqual<byte>(255, pixels[2]);
Assert.AreEqual<byte>(255, pixels[3]);
}
}
The problem is that when I run this test the RendreAsync()
operation lasts forever.
(The cause of that could be that the element
is not a part of the VisualTree, but I cannot find any way to get existing visual tree or to create a new one.)
My question is - how can I make this test work?
回答1:
I've solved the issue.
Using async
await
helps to avoid hanging.
[TestMethod]
public async Task TestMethod2()
{
//pixels to test
byte[] pixels = null;
// Since I create a UI elements, I need to use Dispatcher here.
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, async () =>
{
// Here I create a visual element that I want to test
var brush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));
var element = new Border()
{
MinWidth = 20,
MinHeight = 20,
Background = brush,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
BorderThickness = new Thickness(0)
};
// create an instance of RenderTargetBitmap to render a bitmap
var rtb = new RenderTargetBitmap();
await rtb.RenderAsync(element); // exception!
var pixBuffer = await rtb.GetPixelsAsync();
pixels = pixBuffer.ToArray();
});
Assert.AreEqual<byte>(255, pixels[0]);
Assert.AreEqual<byte>(255, pixels[1]);
Assert.AreEqual<byte>(255, pixels[2]);
Assert.AreEqual<byte>(255, pixels[3]);
}
Ok. Now the test doesn't hang but I get the following exception:
Result Message: Test method UnitTestApp.MyUnitTest.TestMethod2 threw exception: System.NullReferenceException: Object reference not set to an instance of an object.
The reason is that the element
is not a part of the VisualTree. I've found the way to fix that:
var grid = Window.Current.Content as Grid;
grid.Children.Add(element);
Do not forget to remove the element
in the end. And the final version of the test:
[TestMethod]
public async Task TestMethod4()
{
//pixels to test
byte[] pixels = null;
// Since I create a UI elements, I need to use Dispatcher here.
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, async () =>
{
var grid = Window.Current.Content as Grid;
// Here I create a visual element that I want to test
var brush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));
var element = new Border()
{
MinWidth = 20,
MinHeight = 20,
Background = brush,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
BorderThickness = new Thickness(0)
};
grid.Children.Add(element);
try
{
// create an instance of RenderTargetBitmap to render a bitmap
var rtb = new RenderTargetBitmap();
await rtb.RenderAsync(element);
var pixBuffer = await rtb.GetPixelsAsync();
pixels = pixBuffer.ToArray();
}
finally
{
grid.Children.Remove(element);
}
});
Assert.AreEqual<byte>(255, pixels[0]);
Assert.AreEqual<byte>(255, pixels[1]);
Assert.AreEqual<byte>(255, pixels[2]);
Assert.AreEqual<byte>(255, pixels[3]);
}
来源:https://stackoverflow.com/questions/32889152/rendertargetbitmap-in-windows-phone-unit-test-app