如何测试函数是否不抛出异常?

How to test if function does not throw exception?

我有这个功能并测试:

public void SaveForWeb ()
{
    UpdateGameState();
    try
    {
        PlayerPrefs.SetFloat(Helper.EXP_KEY, experience);
        PlayerPrefs.SetFloat(Helper.SCORE_KEY, score);
        // other properties that need to be saved in PlayerPrefs

        PlayerPrefs.Save();
    }
    catch (Exception ex)
    {
        Debug.Log(ex.Message);
    }
}

[Test]
[Category(Helper.TEST_CATEGORY_SAVE_FOR_WEB)]
public void SaveForWebTest ()
{
    // arrange
    var slgdController = FakeSaveLoadGameDataController();
    TestDelegate myDelegate = () => {};

    // act
    slgdController.SaveForWeb();

    // assert
    Assert.DoesNotThrow(myDelegate);
}

但是我感觉这个断言和SaveForWeb()函数的调用没有任何联系。

注意:SaveForWeb() 使用 Unity3D 中的 PlayerPrefs API 如果本地文件超过 1 MB,可能会抛出 PlayerPrefsException。

如果函数不抛出异常,这是断言的正确方法吗?

如果它没有抛出异常,您的代码应该可以正常工作并到达测试方法的末尾。所以你可以在末尾添加一个 Assert.IsTrue(true) 如果 方法 运行 只调用 没有任何错误。否则(如果发生异常)测试将立即停止并且 return false.

编辑:您甚至不需要调用 Assert.IsTrue,如果测试结束,测试也会成功。

正如其他人提到的那样,单元测试将自动失败。但是,如果您确实想为此编写一个断言,请尝试这样的事情。

[Test]
[Category(Helper.TEST_CATEGORY_SAVE_FOR_WEB)]
public void SaveForWebTest ()
{
    // arrange
    var slgdController = FakeSaveLoadGameDataController();
    TestDelegate myDelegate = () => {};

    // act
    try
    {
        slgdController.SaveForWeb();
        Assert.IsTrue(true) // Not Actually necessary as should still pass
    }
    catch (Exception ex)
    {
        Assert.Fail("Expected no exception, but got: " + ex.Message);
    }
}

在我的测试中,我只是不做任何断言。如果抛出异常,测试将失败,因为您没有 ExpectedException 属性等。

Assert.IsTrue(true) 恕我直言

如果方法没有抛出,您不必断言。我知道您正在使用 NUnit,但是有一个 xUnit issue 描述了为什么您不需要断言它。

但是,如果你想明确一点,你可以这样做:

[Test]
[Category(Helper.TEST_CATEGORY_SAVE_FOR_WEB)]
public void SaveForWebTest ()
{
    // arrange
    var slgdController = FakeSaveLoadGameDataController();

    Assert.DoesNotThrow(() => slgdController.SaveForWeb());
}

你应该给你的单元测试起更有意义的名字。这样,你实际上可以从测试中了解哪里出了问题:

    [TestMethod]
    public void SaveForWeb_WhenGameControllerIsOk_DoesNotThrowException()
    {
        // Arrange
        var controller = FakeSaveLoadGameDataController();

        // Act
        controller.SaveForWeb();

        // Assert - Will fail by exceptionThrown
    }

    [TestMethod, ExpectedException(typeof(ReallyBadException))]
    public void SaveForWeb_WhenGameControllerThrowsException_ThrowsException()
    {
        // Arrange
        var controller = new FakeSaveLoadGameDataControllerWithException();

        // Act
        controller.SaveForWeb();
    }