Question

I was wandering if it's possible to mock a Game object in order to test my DrawableGameComponent component?

I know that mocking frameworks need an interface in order to function, but I need to mock the actual Game object.

edit: Here is a link to respective discussion on XNA Community forums. Any help?

Was it helpful?

Solution

There are some good posts in that forum on the topic of unit testing. Here's my personal approach to unit testing in XNA:

  • Ignore the Draw() method
  • Isolate complicated behavior in your own class methods
  • Test the tricky stuff, don't sweat the rest

Here's an example of a test to confirm that my Update method moves Entities the right distance between Update() calls. (I'm using NUnit.) I trimmed out a couple lines with different move vectors, but you get the idea: you shouldn't need a Game to drive your tests.

[TestFixture]
public class EntityTest {
    [Test]
    public void testMovement() {
        float speed = 1.0f; // units per second
        float updateDuration = 1.0f; // seconds
        Vector2 moveVector = new Vector2(0f, 1f);
        Vector2 originalPosition = new Vector2(8f, 12f);

        Entity entity = new Entity("testGuy");
        entity.NextStep = moveVector;
        entity.Position = originalPosition;
        entity.Speed = speed;

        /*** Look ma, no Game! ***/
        entity.Update(updateDuration);

        Vector2 moveVectorDirection = moveVector;
        moveVectorDirection.Normalize();
        Vector2 expected = originalPosition +
            (speed * updateDuration * moveVectorDirection);

        float epsilon = 0.0001f; // using == on floats: bad idea
        Assert.Less(Math.Abs(expected.X - entity.Position.X), epsilon);
        Assert.Less(Math.Abs(expected.Y - entity.Position.Y), epsilon);
    }
}

Edit: Some other notes from the comments:

My Entity Class: I chose to wrap all my game objects up in a centralized Entity class, that looks something like this:

public class Entity {
    public Vector2 Position { get; set; }
    public Drawable Drawable { get; set; }

    public void Update(double seconds) {
        // Entity Update logic...
        if (Drawable != null) {
            Drawable.Update(seconds);
        }
    }

    public void LoadContent(/* I forget the args */) {
        // Entity LoadContent logic...
        if (Drawable != null) {
            Drawable.LoadContent(seconds);
        }
    }
}

This gives me a lot of flexibility to make subclasses of Entity (AIEntity, NonInteractiveEntity...) which probably override Update(). It also lets me subclass Drawable freely, without the hell of n^2 subclasses like AnimatedSpriteAIEntity, ParticleEffectNonInteractiveEntity and AnimatedSpriteNoninteractiveEntity. Instead, I can do this:

Entity torch = new NonInteractiveEntity();
torch.Drawable = new AnimatedSpriteDrawable("Animations\litTorch");
SomeGameScreen.AddEntity(torch);

// let's say you can load an enemy AI script like this
Entity enemy = new AIEntity("AIScritps\hostile");
enemy.Drawable = new AnimatedSpriteDrawable("Animations\ogre");
SomeGameScreen.AddEntity(enemy);

My Drawable class: I have an abstract class from which all my drawn objects are derived. I chose an abstract class because some of the behavior will be shared. It'd be perfectly acceptable to define this as an interface instead, if that's not true of your code.

public abstract class Drawable {
    // my game is 2d, so I use a Point to draw...
    public Point Coordinates { get; set; }
    // But I usually store my game state in a Vector2,
    // so I need a convenient way to convert. If this
    // were an interface, I'd have to write this code everywhere
    public void SetPosition(Vector2 value) {
        Coordinates = new Point((int)value.X, (int)value.Y);
    }

    // This is overridden by subclasses like AnimatedSprite and ParticleEffect
    public abstract void Draw(SpriteBatch spriteBatch, Rectangle visibleArea);
}

The subclasses define their own Draw logic. In your tank example, you could do a few things:

  • Add a new entity for each bullet
  • Make a TankEntity class which defines a List, and overrides Draw() to iterate over the Bullets (which define a Draw method of their own)
  • Make a ListDrawable

Here's an example implementation of ListDrawable, ignoring the question of how to manage the list itself.

public class ListDrawable : Drawable {
    private List<Drawable> Children;
    // ...
    public override void Draw(SpriteBatch spriteBatch, Rectangle visibleArea) {
        if (Children == null) {
            return;
        }

        foreach (Drawable child in children) {
            child.Draw(spriteBatch, visibleArea);
        }
    }
}

OTHER TIPS

frameworks like MOQ and Rhino Mocks don't specifically need an interface. They can mock any non-sealed and/or abstract class as well. Game is an abstract class, so you shouldn't have any trouble mocking it :-)

The one thing to note with at least those two frameworks is that to set any expectations on methods or properties, they must be virtual or abstract. The reason for this is that the mocked instance it generates needs to be able to override. The typemock mentioned by IAmCodeMonkey I believe has a way around this, but I don't think typemock is free, while the two I mentioned are.

As an aside, you can also check out a project of mine that could help in creating unit tests for XNA games without the need to make mocks: http://scurvytest.codeplex.com/

You don't have to mock it. Why not make a fake game object?

Inherit from Game and override the methods you intend to use in your tests to return canned values or shortcut calculations for whatever methods/properties that you need. Then pass the fake to your tests.

Before mocking frameworks, people rolled their own mocks/stubs/fakes - maybe it's not as quick and easy, but you still can.

You can use a tool called TypeMock that I believe does not require you to have an interface. Your other and more commonly followed method is to create a new class that inherits from Game and also implements an interface that you create that matches the Game object. You can then code against that interface and pass in your 'custom' Game object.

public class MyGameObject : Game, IGame
{
    //you can leave this empty since you are inheriting from Game.    
}

public IGame
{
    public GameComponentCollection Components { get; set; }
    public ContentManager Content { get; set; }
    //etc...
}

Its a bit tedious, but it lets you achieve mockability.

I'm gonna piggy back on your post if you don't mind since mine seems to be less active and you already put your rep on the line ;)

As I read through your posts (both here & XNAForum) I'm thinking it's both the framework that could be more approachable and my (our) design that's not flawless.

The framework could have be designed to be easier to extended. I'm having a hard time to believe Shawn's main argument of a perf hit on interfaces. To back me up his colleague says the perf hit could be easely evaded.
Do note that the framework already has an IUpdatable and IDrawable interface. Why not go all the way?

On the other hand I also think that indeed my (and your) design are not flawless. Where I don't depend on the Game object, I do depend on the GraphicsDevice object a lot. I'm gonna look at how I can circumvent this. It's gonna make code more complicated, but I think I can indeed break those dependencies.

For a starting point on something like this, I would hit up the XNA WinForms Sample. Using this sample as a model, it appears that one way to visualize components in a WinForm is to create a control for it in the same style as the SpinningTriangleControl from the sample. This demonstrates how to render XNA code without a Game instance. Really the Game isn't important, its what it does for you that matters. So what you would do is create a Library project which has the Load/Draw logic of the Component in a class and in your other projects, create a Control class and a Component class which are wrappers for the library code in their respective environments. This way, the code your testing isn't duplicated and you don't have to worry about writing code that'll always be viable in two different scenarios.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top