Unit testing custom WPF UIElement rendering

In my application, I use a custom UIElementone that handles its own layout and rendering. Although I can unit test most of this, I can not render unit test correctly. The reason is that the rendering is done using the OnRender method , but I have no way to verify what actually works, since the DrawingContext is an abstract class with an internal constructor, so I cannot extract from it for testing.

The only testing I know is to try different scenarios (based on the implemented code) and check that no exceptions are raised. Is there a way to test more (besides using TypeMock Isolator or JustMock)?

+4
source share
2 answers

I wrote an answer in this thread: testing unit of a custom OnRender method

Nevertheless, I am copying the answer to this thread (someone can delete it if not needed).

The solution is to create DrawingContextfrom DrawingGroup.

public class TestingMyControl : MyControl
{
    public DrawingGroup Render()
    {
        var drawingGroup = new DrawingGroup();
        using (var drawingContext = drawingGroup.Open())
        {
             base.OnRender(drawingContext);
        }
        return drawingGroup;
    }
}

So, the device will look like this:

    [Test]
    public void Should_render()
    {
        var controlToTest = new TestingMyControl();

        var drawingGroup = controlToTest.Render();

        var drawing = drawingGroup.Children[0] as GeometryDrawing;
        Assert.That(drawing.Brush, Is.EqualTo(Brushes.Black));
        Assert.That(drawing.Pen.Brush, Is.EqualTo(Brushes.SeaGreen));
        Assert.That(drawing.Pen.Thickness, Is.EqualTo(0.6));
        Assert.That(drawing.Bounds.X, Is.EqualTo(5));
        Assert.That(drawing.Bounds.Y, Is.EqualTo(15));
        Assert.That(drawing.Bounds.Width, Is.EqualTo(25));
        Assert.That(drawing.Bounds.Height, Is.EqualTo(35));
    }

This requires a production code code:

public class MyControl : Canvas
{
    protected override void OnRender(DrawingContext dc)
    {
        dc.DrawRectangle(Brushes.Black, new Pen(Brushes.SeaGreen, 0.6), new Rect(5, 15, 25, 35));
    }
}
+5
source

, InvalidateVisual, InvalidateArrange . OnRender , WPF ( InvalidateArrange) ( InvalidateVisual).

FrameworkPropertyMetadata.AffectsRende r WPF InvalidateVisual .

( MainControl), OnRender , InvalidateVisual , . , WPF , , .

, (, NestedControl), MainControl. MainControl ControlTemplate, z-. InvalidateNestedControl MainControl, InvalidateVisual NestedControl.

. , ...

public class TestPanel : DockPanel
{
    protected override Size MeasureOverride(Size constraint)
    {
        System.Console.WriteLine("MeasureOverride called for " + this.Name + ".");
        return base.MeasureOverride(constraint);
    }
protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
{
    System.Console.WriteLine("ArrangeOverride called for " + this.Name + ".");
    return base.ArrangeOverride(arrangeSize);
}

protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
    System.Console.WriteLine("OnRender called for " + this.Name + ".");
    base.OnRender(dc);
}

}

... ( , ):

<Button Content="Test" Click="Button_Click" DockPanel.Dock="Top" HorizontalAlignment="Left" />

<l:TestPanel x:Name="InnerPanel" Background="Red" Margin="16" />

, ...

MeasureOverride MainTestPanel. MeasureOverride InnerPanel. ArrangeOverride MainTestPanel. ArrangeOverride InnerPanel. OnRender InnerPanel. OnRender MainTestPanel. InvalidateVisual "MainTestPanel" ( 'Click'), ...

ArrangeOverride MainTestPanel. OnRender MainTestPanel. , , ArrangeOverride .

, ArrangeOverride (, , ), (), , , .

, , AffectsParentArrange ( , ), Nullable Size ArrangeOverride, , , ...

public class TestPanel : DockPanel
{
    Size? arrangeResult;

protected override Size MeasureOverride(Size constraint)
{
    arrangeResult = null;
    System.Console.WriteLine("MeasureOverride called for " + this.Name + ".");
    return base.MeasureOverride(constraint);
}

protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
{
    if(!arrangeResult.HasValue)
    {
        System.Console.WriteLine("ArrangeOverride called for " + this.Name + ".");
        // Do your arrange work here
        arrangeResult = base.ArrangeOverride(arrangeSize);
    }

    return arrangeResult.Value;
}

protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
    System.Console.WriteLine("OnRender called for " + this.Name + ".");
    base.OnRender(dc);
}

}

, - ( MeasureOverride), OnRender, Arrange, , InvalidateVisual.

0

Source: https://habr.com/ru/post/1535545/


All Articles