Xamarin.UITest启动时NSUserDefaults plist文件丢失无法重建求助
我之前也踩过这个坑——用UITest默认启动模式清数据时,NSUserDefaults的配置文件直接被删,就算调用Synchronize()也没法重建。结合你「每次启动清数据但要保留/重建环境配置」的需求,给你几个实用的解决方案:
1. 应用启动时自动初始化环境配置
在AppDelegate的FinishedLaunching方法里,检查必要的环境配置键是否存在,不存在就自动写入默认值。这样不管UITest怎么清数据,应用启动时都会主动重建NSUserDefaults的plist并写入配置:
public override bool FinishedLaunching(UIApplication app, NSDictionary options) { var defaults = NSUserDefaults.StandardUserDefaults; // 检查Web服务URL是否存在,不存在则写入默认值 if (defaults.StringForKey("WebServiceUrl") == null) { defaults.SetString("https://your-production-api.com", "WebServiceUrl"); // 强制写入磁盘 defaults.Synchronize(); } // 其他应用初始化逻辑... return true; }
这个方案最省心,适合需要固定默认环境配置的场景,不管是正常启动还是UITest启动,都能保证配置不会丢。
2. UITest启动后主动设置测试环境配置
如果你的UITest需要用特定的测试环境URL,可以在应用里暴露一个可被UITest调用的方法,启动后直接设置配置:
第一步:在Xamarin.iOS应用中添加可调用方法
给AppDelegate或者其他全局类添加标记[Export]的方法:
[Foundation.Export("setTestWebServiceUrl:")] public void SetTestWebServiceUrl(string testUrl) { var defaults = NSUserDefaults.StandardUserDefaults; defaults.SetString(testUrl, "WebServiceUrl"); defaults.Synchronize(); }
第二步:在UITest中调用该方法
保持默认的StartApp()(默认会清除沙盒数据),启动后立刻调用方法设置测试配置:
app = ConfigureApp .iOS .PreferIdeSettings() .EnableLocalScreenshots() .DeviceIdentifier("guid") .InstalledApp("bundle_identifier") .StartApp(); // 默认是Clear模式,清除所有沙盒数据 // 调用应用内的方法设置测试环境URL app.Invoke("setTestWebServiceUrl:", "https://test-api.yourdomain.com");
这个方案灵活度拉满,不同的UITest用例可以设置不同的环境URL,完美满足「每次清数据但配置正确」的需求。
3. 分离环境配置与用户数据
如果不想让UITest的清除操作影响环境配置,可以把环境信息存在自定义的plist文件里(比如打包时嵌入的资源文件),而非NSUserDefaults的默认plist:
// 读取嵌入Bundle的默认配置 var configPath = Path.Combine(NSBundle.MainBundle.BundlePath, "EnvConfig.plist"); var defaultConfig = NSDictionary.FromFile(configPath); var defaultWebUrl = defaultConfig["WebServiceUrl"].ToString(); // 首次启动时,将默认配置复制到Documents目录(避免被UITest清除后丢失) var docsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var savedConfigPath = Path.Combine(docsPath, "SavedEnvConfig.plist"); if (!File.Exists(savedConfigPath)) { File.Copy(configPath, savedConfigPath); } // 使用配置时读取SavedEnvConfig.plist var currentConfig = NSDictionary.FromFile(savedConfigPath); var webUrl = currentConfig["WebServiceUrl"].ToString();
不过这个方案需要额外的配置管理逻辑,适合对配置隔离要求很高的场景。
核心原因说明
UITest默认的StartApp()用的是AppDataMode.Clear模式,会彻底删除应用的沙盒目录,包括NSUserDefaults对应的Library/Preferences/[bundle-id].plist文件。如果没有主动写入键值对,就算调用Synchronize(),系统也不会自动重建这个plist——这就是同步没用的根本原因。上面的方案本质都是确保UITest清数据后,应用能主动写入配置,触发plist文件的重建。
内容的提问来源于stack exchange,提问作者Ramesh Annadurai

