using System.Reflection; using BulkArchiveMailer.Core; using Xunit; namespace BulkArchiveMailer.Core.Tests { /// /// Covers the one AppSettingsData behavior that's easy to silently /// break when adding a field: loading a config.json written before /// FromAccountSmtpAddress existed must not throw, and a non-empty /// value must round-trip once the operator picks a "from" account in /// SettingsForm. /// /// Note the old-JSON case asserts null, not "": DataContractJsonSerializer /// builds the target via FormatterServices.GetUninitializedObject, /// which skips this property's "" initializer entirely for any member /// absent from the source JSON, leaving the CLR default (null) - see /// the long comment on AppSettingsData.FromAccountSmtpAddress. Every /// call site (MailSender, SettingsForm) already treats null the same /// as "" for this reason. /// /// Goes through AppSettings' private Serialize/Deserialize via /// reflection rather than Load()/Save(), so this test never touches /// the real %APPDATA%\BulkArchiveMailer\config.json on the machine /// running it. /// public class AppSettingsTests { [Fact] public void Deserialize_OldJsonWithoutFromAccountField_DoesNotThrowAndTreatsAsUnset() { const string oldJson = @"{ ""archiveFolder"": ""C:\\archives"", ""emailDomain"": ""redlab.lo"", ""testModeDefault"": true, ""signatureHtmlPath"": """" }"; var settings = InvokeDeserialize(oldJson); Assert.True(string.IsNullOrEmpty(settings.FromAccountSmtpAddress)); Assert.Equal("redlab.lo", settings.EmailDomain); } [Fact] public void SerializeThenDeserialize_RoundTripsFromAccountSmtpAddress() { var data = new AppSettingsData { ArchiveFolder = "C:\\archives", EmailDomain = "redlab.lo", FromAccountSmtpAddress = "svc-mailer@redlab.lo", }; var json = InvokeSerialize(data); var roundTripped = InvokeDeserialize(json); Assert.Equal("svc-mailer@redlab.lo", roundTripped.FromAccountSmtpAddress); } private static AppSettingsData InvokeDeserialize(string json) { var method = typeof(AppSettings).GetMethod("Deserialize", BindingFlags.NonPublic | BindingFlags.Static); return (AppSettingsData)method.Invoke(null, new object[] { json }); } private static string InvokeSerialize(AppSettingsData data) { var method = typeof(AppSettings).GetMethod("Serialize", BindingFlags.NonPublic | BindingFlags.Static); return (string)method.Invoke(null, new object[] { data }); } } }