4

I have this function and test:

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);
}

But I feel there is no connection between the assertion and the call of SaveForWeb() function.

Note: SaveForWeb() uses PlayerPrefs from the Unity3D API which might throw PlayerPrefsException if the local file exceedes 1 MB.

Is this the right way to assert if function does not throw exception?

Vlad
  • 2,739
  • 7
  • 49
  • 100
  • You don't need to assert that a function does not throw an exception in a unit test. By default, if an exception is thrown in a unit test then the unit test will fail due to an unexpected exception. – Matthew Watson Mar 03 '16 at 11:50
  • 1
    Yes its a duplicate but ok, somebody from the Unity3D community might find it useful. – Vlad Mar 03 '16 at 12:00
  • Nothing wrong with duplicates if useful (and presumably innocent) :p – Drew Mar 04 '16 at 00:54
  • So I read the xUnit issue below- and boy was it spicy. In short- they did get rid of DoesNotThrow. I guess I am in the opinionated camp that it should have stayed- however it's far too late for that. For those looking for a way to explictly declare this in your tests, you can also check this using Record.Exception or trying to get an exception- if no exception occurs it will return null: var exception = Record.Exception(() => act()); Assert.Null(exception); – Tabrock Feb 20 '23 at 22:26

5 Answers5

7

You don't have to assert if the method doesn't throw. I know you're using NUnit, but there's a xUnit issue that describes why you don't need to assert it.

However, if you want to be explicit, you can do:

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

    Assert.DoesNotThrow(() => slgdController.SaveForWeb());
}
Marcio Rinaldi
  • 3,305
  • 24
  • 23
6

If it does not throw an exception your code should simply work and reach the end of the test-method. So you can add an Assert.IsTrue(true) at end which is only called if the method ran without any error. Otherwise (if an exception occurs) the test will immediately stop and return false.

EDIT: You do not even need a call to Assert.IsTrue, the test will also succeed if it reaches the end.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
4

In my tests, I just make no assertion. If an exception is thrown, the test would failed cause you don't have an ExpectedException attribute or so.

Assert.IsTrue(true) is meaningless imho

cdie
  • 4,014
  • 4
  • 34
  • 57
3

As others have mentioned the unit test will fail automatically. However, if you really did want to write an assertion for this try something like this.

[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);
    }
}
Vlad
  • 2,739
  • 7
  • 49
  • 100
KevDev
  • 336
  • 1
  • 8
1

You should give your Unit tests more meaningful names. This way, you can actually understand from the test what is going wrong:

    [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();
    }
Pedro G. Dias
  • 3,162
  • 1
  • 18
  • 30