Any interest in a testable MonoGame wrapper?

Hey guys,

So a while back I decided I wanted to try to release a game since it’s something I’ve always wanted to do. I think I’m even, maybe, getting fairly close to doing that (lol :P). One of the goals I set out with this project though is that I wanted to ensure that all of the code I write is backed by unit tests.

Since the XNA framework (and by extension, MonoGame) was never really designed with unit testing/mocking in mind, I’ve ended up creating several wrappers for MonoGame objects so that I can interact with code at a more abstract level. This is generally fairly easy to achieve, involving creating an interface from the existing object and then implementing that interface with a wrapper for the MonoGame object. Your code can then interact with the interface, allowing you to easily mock it in a unit test.

Here’s a very brief example of an object responsible for drawing a texture with various parameters. Utilizing the wrappers, I can then write a unit test to ensure that the draw call does the expected things. In this way, if I ever change the code to include more functionality, I can have confidence that my intended functionality still works… or doesn’t, resulting in a bunch of failed tests that I can then either address by correcting, or updating the tests.

// Sample object
public class SimpleGameDrawable
{
    private ISpriteBatch _spriteBatch;
    private ITexture2D _texture;

    public Vector2 Location { get; set; } = Vector2.Zero;
    public Color Color { get; set; } = Color.White;

    public SimpleGameDrawable(ISpriteBatch spriteBatch, ITexture2D texture)
    {
        _spriteBatch = spriteBatch ?? throw new ArgumentNullException();
        _texture = texture ?? throw new ArgumentNullException();
    }
    
    public void Draw(GameTime gameTime)
    {
        _spriteBatch.Begin();
        _spriteBatch.Draw(_texture, this.Location, this.Color;
        _spriteBatch.End();
    }
}

// Sample test class using MSTEST and NSubstitute for mocking
[TestClass]
public class SimpleGameDrawable_Tests
{
    private SimpleGameDrawable _sut;
    
    private ISpriteBatch _mockSpriteBatch;
    private ITexture2D _mockTexture;
    
    [TestInitialize]
    public void Initialize()
    {
        _mockSpriteBatch = Substitute.For<ISpriteBatch>();
        _mockTexture = Substitute.For<ITexture2D>();
        
        _sut = new SimpleGameDrawable(_mockSpriteBatch, _mockTexture)
        {
            Location = new Vector2(123, 321),
            Color = Color.Pink,
        };
    }
    
    [TestMethod]
    public void DrawShouldBeginThenEndSpriteBatch()
    {
        _sut.Draw(new GameTime());
        
        Received.InOrder(
            () =>
            {
                _mockSpriteBatch.Begin();
                _mockSpriteBatch.End();
            }
        );
    }
    
    [TestMethod]
    public void DrawShouldCallSpriteBatchDrawWithExpectedParameters()
    {
        _sut.Draw(new GameTime());
        
        _mockSpriteBatch.Received(1).Draw(_mockTexture, new Vector2(123, 321), Color.Pink);
    }
}

Anyway, this has been an ongoing development so the wrapper is by no means complete… my approach is to just implement the things I need to achieve my goals, then stop there. That said, I’m wondering if this is something that would interest other people. I currently have this code sitting in a private repository with the rest of my stuff, but if there were interest I could upload it to github or something, as well as continue the project to include functionality I currently don’t use. I could probably also write up some tutorials on applying testing to MonoGame development.

Any thoughts on this?