I have a code of my Save() function, it has only switch statement inside. So basically it saves based on the platform chosen. However I already have tests for UpdateGameState(), SaveForWeb() and SaveForX86() functions. Since Unit Testing rules say, if you have a logic in your function no matter how simple it is, you have to test that function.
public void Save ()
{
switch(Helper.BUILD_TYPE)
{
case Helper.BUILD_FOR_WEB:
SaveForWeb();
break;
case Helper.BUILD_FOR_WIN_X86:
SaveForX86();
break;
default:
Debug.Log("Save method: " + Helper.WRONG_BUILD_TYPE_SELECTED_ERR);
break;
}
}
Also calling test inside a test breaks the isolation rule of tests, so it seems I have to copy the testing logic inside my other tests just to check whether the Save() logic works all the way after SaveForWeb() and SaveForX86().
In these circumstances, how would you test this function?
I can do this in my tests:
Helper.BUILD_TYPE = Helper.BUILD_FOR_WEB;
Where BUILD_TYPE is static but not constant as BUILD_FOR_WEB and BUILD_FOR_WIN_X86.
Here is the class under test:
using UnityEngine;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class SaveLoadGameData : MonoBehaviour
{
public static SaveLoadGameData gameState;
public float experience = Helper.DEFAULT_EXPERIENCE;
public float score = Helper.DEFAULT_SCORE;
void Awake ()
{
Init();
}
public void Init()
{
if (gameState == null)
{
DontDestroyOnLoad(gameObject);
gameState = this;
}
else if (gameState != this)
{
Destroy(gameObject);
}
}
public void SaveForWeb ()
{
UpdateGameState();
try
{
PlayerPrefs.SetFloat(Helper.EXP_KEY, experience);
PlayerPrefs.SetFloat(Helper.SCORE_KEY, score);
PlayerPrefs.Save();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
public void SaveForX86 ()
{
UpdateGameState();
try
{
BinaryFormatter bf = new BinaryFormatter();
FileStream fs = File.Create(Application.persistentDataPath + Helper.GAME_DATA_FILE_NAME);
GameData data = new GameData();
data.experience = experience;
data.score = score;
bf.Serialize(fs, data);
fs.Close();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
public void Save ()
{
switch(Helper.BUILD_TYPE)
{
case Helper.BUILD_FOR_WEB:
SaveForWeb();
break;
case Helper.BUILD_FOR_WIN_X86:
SaveForX86();
break;
case Helper.BUILD_FOR_ANDROID:
break;
default:
Debug.Log("Save method: " + Helper.WRONG_BUILD_TYPE_SELECTED_ERR);
break;
}
}
public void LoadForWeb ()
{
try
{
experience = PlayerPrefs.GetFloat(Helper.EXP_KEY, Helper.DEFAULT_EXPERIENCE);
score = PlayerPrefs.GetFloat(Helper.SCORE_KEY, Helper.DEFAULT_SCORE);
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
public void LoadForX86 ()
{
try
{
if (File.Exists(Application.persistentDataPath + Helper.GAME_DATA_FILE_NAME))
{
BinaryFormatter bf = new BinaryFormatter();
FileStream fs = File.Open(Application.persistentDataPath + Helper.GAME_DATA_FILE_NAME, FileMode.Open);
GameData data = (GameData)bf.Deserialize(fs);
experience = data.experience;
score = data.score;
fs.Close();
}
else
{
Save();
}
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
public void Load ()
{
switch(Helper.BUILD_TYPE)
{
case Helper.BUILD_FOR_WEB:
LoadForWeb();
break;
case Helper.BUILD_FOR_WIN_X86:
LoadForX86();
break;
case Helper.BUILD_FOR_ANDROID:
break;
default:
Debug.Log("Load method: " + Helper.WRONG_BUILD_TYPE_SELECTED_ERR);
break;
}
UpdateGameState();
}
public void UpdateGameState ()
{
gameState.experience = experience;
gameState.score = score;
}
public void ResetGameState ()
{
experience = Helper.DEFAULT_EXPERIENCE;
score = Helper.DEFAULT_SCORE;
Save();
}
}
[Serializable]
class GameData
{
public float experience = Helper.DEFAULT_EXPERIENCE;
public float score = Helper.DEFAULT_SCORE;
}
Note: I removed UpdateGameState() from Save() and now it is both SaveForWeb() and SaveForX86().