Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test drawing graphics?

Tags:

c#

moq

nunit

My application (C#, WinForms) is a graphic editor, so drawing is a major part of functionality. I am having difficulties unit testing logic around drawing, which makes me think that my design is wrong. Let me describe it and I'd like some advice on either how to unit test or how to refactor my app's logic.

All drawing is handled by a manager (DrawingManager) which does geometric calculations and interacts with drawing canvases of controls that display the result. A typical method of this manager would be invoked with a reference to a drawing canvas (Graphics). Somewhere in the app's surface events (like OnPaint) we give control to the manager which decides what to draw and how, and then draws. To draw, it needs to hold a reference to the Graphics object, which is why it is passed to the manager's method from the event.

    protected override void OnPaint(PaintEventArgs e)
    {            
        IZoomBoxDrawingManager drawingManager = ServiceLocator.Instance.Resolve<IZoomBoxDrawingManager>();
        drawingManager.DrawMainImage(this, e.Graphics);
        drawingManager.DrawObjects(this, e.Graphics);

        base.OnPaint(e);
    }

Now, let's say, DrawObjects invokes either one path of logic or the other before it starts calling Graphics' methods to output the geometry. I would like to somehow unit test the logic within this manager, but its coupling with Graphics instances makes it somehow impossible, at least I don't know how to do it. Moq which I use for isolating can't mock a sealed class. It would be sweet if I could put in some kind of registrator instead of Graphics and be able to see what methods of Graphics are invoked and when. Please advise!

like image 712
Yuri Makassiouk Avatar asked Dec 05 '25 05:12

Yuri Makassiouk


1 Answers

Consider using the Adapter pattern to wrap the functionality needed by the Graphics object in an interface.

interface IGraphics
{
    void DrawCircle(int x,int y,int d);
}

public class GraphicsAdapter : IGraphics
{
    private readonly Graphics graphics;

    public GraphicsAdapter(Graphics g)
    {
        this.graphics = g;
    }

    public void DrawCircle(int x, int y, int d)
    {
        graphics.DrawCircle(x, y, d);
    }
}

Now your DrawingManager can have a dependency on the IGraphics interface instead of the sealed Graphics object. You can mock it during testing but use the adapter at runtime:

drawingManager.DrawObjects(this, new GraphicsAdapter(e.Graphics));
like image 128
PatrickSteele Avatar answered Dec 07 '25 19:12

PatrickSteele



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!