Unity 播放模式测试中的代码中未调用 Moq 的模拟方法

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

如果我模拟一个方法,我是否必须显式调用该方法来运行我的模拟实现?

我正在尝试在 Unity 项目中进行模拟。我基本上正在启动一个场景,并在 Start() 方法中执行代码。我正在尝试模拟该启动方法中发生的休息调用。

这是我的代码:

public class MyAddressablesClass
{
    public virtual IEnumerator LoadRemoteCatalog()
    {
        // My implementation here
    }
}

public class MyCode
{
    public IEnumerator Start()
    {
        // Doing some stuff
        MyAddressablesClass myAddressablesInstance = new MyAddressablesClass();
        yield return myAddressablesInstance.LoadRemoteCatalog();
        // Doing some other stuff
    }
}
        

这是我的模拟实现:

private IEnumerator GetFakeCatalog() {
    yield return null;
}

[UnitySetUp]
public IEnumerator Setup()
{
    Mock<MyAddressablesClass> mockedClass = new Mock<MyAddressablesClass>();
    mockedClass.Setup(service => service.LoadRemoteCatalog()).Returns(GetFakeCatalog());
}

[UnityTest]
public IEnumerator TestThings() {
    yield return SceneManager.LoadSceneAsync("MyScene");
}

当我运行单元测试时,我不想明确地说

var mocked = new MyAddressablesClass(mockedClass.Object); yield return mocked.LoadRemoteCatalog();
以便调用
GetFakeCatalog()

在我的实际代码中调用

LoadRemoteCatalog()
时,它不应该自动使用我的模拟实现吗?

我想测试场景启动时发生的所有情况,所以我不想嘲笑它。

c# unit-testing mocking moq
1个回答
0
投票

起订量并不神奇;它只会在您配置的对象上实现特定于测试的行为。

当您在被测系统 (SUT) 中编写时

MyAddressablesClass myAddressablesInstance = new MyAddressablesClass();

SUT 将使用该

MyAddressablesClass
实例,就像代码所示;不是
mockedClass

测试创建

Mock<MyAddressablesClass>
是无关紧要的。它们是两个不同的对象。

如果您希望能够更改

MyAddressablesClass
内部
MyCode.Start
的行为,则必须以某种方式传递该对象。

根据需求,我建议使用构造函数注入或方法注入。

在这两种情况下,测试现在都能够将

mockedClass.Instance
传递给 SUT。

构造函数注入

public class MyCode
{
    private readonly MyAddressablesClass myAddressablesInstance;

    public MyCode(MyAddressablesClass myAddressablesInstance)
    {
        this.myAddressablesInstance = myAddressablesInstance;
    }

    public IEnumerator Start()
    {
        // Doing some stuff
        yield return myAddressablesInstance.LoadRemoteCatalog();
        // Doing some other stuff
    }
}

方法注入

public class MyCode
{
    public IEnumerator Start(MyAddressablesClass myAddressablesInstance)
    {
        // Doing some stuff
        yield return myAddressablesInstance.LoadRemoteCatalog();
        // Doing some other stuff
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.