可单元测试的单游戏:最佳方法?

问题描述 投票:0回答:1

我正在尝试在 monogame 之上建立一个框架。我真的希望该框架可以进行单元测试。

比如我写过一个

SpriteComponent
的课。如果我可以创建一个快速测试来验证组件的
OffsetType
属性是否有效,那就太好了。像这样的东西:

[Fact]
public void SpriteOffsetTypeWorks()
{
    AminoGame game = new AminoGame();
    Scene scene = new Scene(game);
    Entity entity = new Entity(scene);
    SpriteComponent sprite = new SpriteComponent(entity);

    sprite.OffsetType = AnchorType.Centre;
    Assert.Equal(new Vector2(0.5f, 0.5f), sprite.OffsetFactor);
}

对于上下文,

AminoGame
继承自Monogame的
Game
类。

问题在于,虽然

Game
中固有的某些服务在单元测试中正确初始化,但其他服务却没有,特别是
GraphicsDevice
。这是有道理的,因为我的单元测试没有创建图形环境。

为了尝试解决这个问题,我

  1. 尝试将视图与模型分开:我从
    SpriteComponent
    中删除了所有“渲染”代码,并将其放置在其他地方,在一个不会在非图形设置中调用的代码区域。
  2. 写了一个环绕
    AminoGame
    的接口,但我也可以环绕一个虚拟类,我将在单元测试中使用它。

这种做法还是有问题的。例如:

public class SpriteComponent : Component
{
    public Texture2D Texture => _texture;
    protected Texture2D _texture;

    public SpriteComponent(Entity owner) : base(owner)
    {
        if (Config.DefaultSprite == null)
        {
            throw new InvalidOperationException($"Cannot call {nameof(SpriteComponent)} constructor with unspecified sprite: Specify a default sprite in {nameof(Config.DefaultSprite)}.");
        }
        _texture = World.Content.Load<Texture2D>(Config.DefaultSprite);
    }
}

我编写的

SpriteComponent
类能够在未指定纹理的情况下加载默认纹理。但是
Texture2D
是一个图形对象,所以 Monogame 再次抱怨它在尝试加载时没有
GraphicsDevice

这让我想知道:我是否想要在单元测试中使用纹理或 3D 模型?如果没有,那我怎么写

SpriteComponent
的方式完全可以在没有图形的情况下运行?

但更广泛地说,我还依赖哪些其他服务,我不知道,在单元测试中不可用?

我的方法是错误的吗?有更好的方法吗?

c# unit-testing architecture monogame
1个回答
0
投票

所以,老实说,我根本不知道 monogame。但这些年来我使用了数十种框架,其中大多数在单元测试方面都很糟糕。问题是,当您将代码与框架分离到足以对其进行单元测试时,您通常会失去在该框架中编码的大部分优势。你的代码变得非常臃肿,主要是因为它不能使用框架并进行单元测试。

有些框架内置了可单元测试的模拟(这些很好!)但不是特别常见。快速谷歌搜索导致:https://community.monogame.net/t/unit-testing-best-practices/2638/2,这并不是特别令人鼓舞。基本上,我的经验法则是,如果一个框架需要继承,单元测试将很难(因为你不能注入模拟/存根)。集成测试很可能是您最好的方法。

© www.soinside.com 2019 - 2024. All rights reserved.