diff --git a/test/toolkit/Community.VisualStudio.Toolkit.UnitTests/Community.VisualStudio.Toolkit.UnitTests.csproj b/test/toolkit/Community.VisualStudio.Toolkit.UnitTests/Community.VisualStudio.Toolkit.UnitTests.csproj index 322905d..7777e81 100644 --- a/test/toolkit/Community.VisualStudio.Toolkit.UnitTests/Community.VisualStudio.Toolkit.UnitTests.csproj +++ b/test/toolkit/Community.VisualStudio.Toolkit.UnitTests/Community.VisualStudio.Toolkit.UnitTests.csproj @@ -19,8 +19,8 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/toolkit/Community.VisualStudio.Toolkit.UnitTests/OptionModelPropertyWrapperTests.cs b/test/toolkit/Community.VisualStudio.Toolkit.UnitTests/OptionModelPropertyWrapperTests.cs index 2e55ac9..a0f5547 100644 --- a/test/toolkit/Community.VisualStudio.Toolkit.UnitTests/OptionModelPropertyWrapperTests.cs +++ b/test/toolkit/Community.VisualStudio.Toolkit.UnitTests/OptionModelPropertyWrapperTests.cs @@ -9,7 +9,8 @@ using System.Text; using FluentAssertions; using Microsoft.VisualStudio.Settings; -using Moq; +using NSubstitute; +using NSubstitute.Exceptions; using Xunit; using Xunit.Abstractions; @@ -599,21 +600,21 @@ private void SettingStoreTest_String(BaseOptionModel? overrideAssertEquality = null) where TOptMdl : BaseOptionModel, new() { - Mock mock = new(); - mock.Setup(x => x.CollectionExists(collectionPath)).Returns(true); - mock.Setup(x => x.PropertyExists(collectionPath, propertyName)).Returns(true); + WritableSettingsStore mock = Substitute.For(); + mock.CollectionExists(collectionPath).Returns(true); + mock.PropertyExists(collectionPath, propertyName).Returns(true); void SetupSettingsStoreGet(string valueToReturn) { - mock.Setup(x => x.GetString(collectionPath, propertyName)).Returns(valueToReturn); + mock.GetString(collectionPath, propertyName).Returns(valueToReturn); } - Action verifyGet = (int callCount, string failMessage) => - mock.Verify(x => x.GetString(collectionPath, propertyName), Times.Exactly(callCount), failMessage); - Action verifySet = (int callCount, string expectedValue, string failMessage) => - mock.Verify(x => x.SetString(collectionPath, propertyName, expectedValue), Times.Exactly(callCount), failMessage); + Action verifyGet = (int callCount) => + mock.Received(callCount).GetString(collectionPath, propertyName); + Action verifySet = (int callCount, string expectedValue) => + mock.Received(callCount).SetString(collectionPath, propertyName, expectedValue); - SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock.Object, SetupSettingsStoreGet, verifyGet, verifySet, + SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock, SetupSettingsStoreGet, verifyGet, verifySet, defaultValueProperty, expectedDefaultValueInStore, expectedAlternateValueProperty, expectedAlternateValueInStore, overrideAssertEquality); } @@ -646,22 +647,21 @@ private void SettingStoreTest_Int32(BaseOptionModel, new() { - Mock mock = new(); - mock.Setup(x => x.CollectionExists(collectionPath)).Returns(true); - mock.Setup(x => x.PropertyExists(collectionPath, propertyName)).Returns(true); - mock.Setup(x => x.SetInt32(collectionPath, propertyName, It.IsAny())); + WritableSettingsStore mock = Substitute.For(); + mock.CollectionExists(collectionPath).Returns(true); + mock.PropertyExists(collectionPath, propertyName).Returns(true); void SetupSettingsStoreGet(int valueToReturn) { - mock.Setup(x => x.GetInt32(collectionPath, propertyName)).Returns(valueToReturn); + mock.GetInt32(collectionPath, propertyName).Returns(valueToReturn); } - Action verifyGet = (int callCount, string failMessage) => - mock.Verify(x => x.GetInt32(collectionPath, propertyName), Times.Exactly(callCount), failMessage); - Action verifySet = (int callCount, int expectedValue, string failMessage) => - mock.Verify(x => x.SetInt32(collectionPath, propertyName, expectedValue), Times.Exactly(callCount), failMessage); + Action verifyGet = (int callCount) => + mock.Received(callCount).GetInt32(collectionPath, propertyName); + Action verifySet = (int callCount, int expectedValue) => + mock.Received(callCount).SetInt32(collectionPath, propertyName, expectedValue); - SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock.Object, SetupSettingsStoreGet, verifyGet, verifySet, + SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock, SetupSettingsStoreGet, verifyGet, verifySet, defaultValueProperty, expectedDefaultValueInStore, expectedAlternateValueProperty, expectedAlternateValueInStore); } @@ -694,22 +694,21 @@ private void SettingStoreTest_UInt32(BaseOptionModel, new() { - Mock mock = new(); - mock.Setup(x => x.CollectionExists(collectionPath)).Returns(true); - mock.Setup(x => x.PropertyExists(collectionPath, propertyName)).Returns(true); - mock.Setup(x => x.SetUInt32(collectionPath, propertyName, It.IsAny())); + WritableSettingsStore mock = Substitute.For(); + mock.CollectionExists(collectionPath).Returns(true); + mock.PropertyExists(collectionPath, propertyName).Returns(true); void SetupSettingsStoreGet(uint valueToReturn) { - mock.Setup(x => x.GetUInt32(collectionPath, propertyName)).Returns(valueToReturn); + mock.GetUInt32(collectionPath, propertyName).Returns(valueToReturn); } - Action verifyGet = (int callCount, string failMessage) => - mock.Verify(x => x.GetUInt32(collectionPath, propertyName), Times.Exactly(callCount), failMessage); - Action verifySet = (int callCount, uint expectedValue, string failMessage) => - mock.Verify(x => x.SetUInt32(collectionPath, propertyName, expectedValue), Times.Exactly(callCount), failMessage); + Action verifyGet = (int callCount) => + mock.Received(callCount).GetUInt32(collectionPath, propertyName); + Action verifySet = (int callCount, uint expectedValue) => + mock.Received(callCount).SetUInt32(collectionPath, propertyName, expectedValue); - SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock.Object, SetupSettingsStoreGet, verifyGet, verifySet, + SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock, SetupSettingsStoreGet, verifyGet, verifySet, defaultValueProperty, expectedDefaultValueInStore, expectedAlternateValueProperty, expectedAlternateValueInStore); } @@ -742,22 +741,21 @@ private void SettingStoreTest_Int64(BaseOptionModel, new() { - Mock mock = new(); - mock.Setup(x => x.CollectionExists(collectionPath)).Returns(true); - mock.Setup(x => x.PropertyExists(collectionPath, propertyName)).Returns(true); - mock.Setup(x => x.SetInt64(collectionPath, propertyName, It.IsAny())); + WritableSettingsStore mock = Substitute.For(); + mock.CollectionExists(collectionPath).Returns(true); + mock.PropertyExists(collectionPath, propertyName).Returns(true); void SetupSettingsStoreGet(long valueToReturn) { - mock.Setup(x => x.GetInt64(collectionPath, propertyName)).Returns(valueToReturn); + mock.GetInt64(collectionPath, propertyName).Returns(valueToReturn); } - Action verifyGet = (int callCount, string failMessage) => - mock.Verify(x => x.GetInt64(collectionPath, propertyName), Times.Exactly(callCount), failMessage); - Action verifySet = (int callCount, long expectedValue, string failMessage) => - mock.Verify(x => x.SetInt64(collectionPath, propertyName, expectedValue), Times.Exactly(callCount), failMessage); + Action verifyGet = (int callCount) => + mock.Received(callCount).GetInt64(collectionPath, propertyName); + Action verifySet = (int callCount, long expectedValue) => + mock.Received(callCount).SetInt64(collectionPath, propertyName, expectedValue); - SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock.Object, SetupSettingsStoreGet, verifyGet, verifySet, + SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock, SetupSettingsStoreGet, verifyGet, verifySet, defaultValueProperty, expectedDefaultValueInStore, expectedAlternateValueProperty, expectedAlternateValueInStore); } @@ -790,22 +788,21 @@ private void SettingStoreTest_UInt64(BaseOptionModel, new() { - Mock mock = new(); - mock.Setup(x => x.CollectionExists(collectionPath)).Returns(true); - mock.Setup(x => x.PropertyExists(collectionPath, propertyName)).Returns(true); - mock.Setup(x => x.SetUInt64(collectionPath, propertyName, It.IsAny())); + WritableSettingsStore mock = Substitute.For(); + mock.CollectionExists(collectionPath).Returns(true); + mock.PropertyExists(collectionPath, propertyName).Returns(true); void SetupSettingsStoreGet(ulong valueToReturn) { - mock.Setup(x => x.GetUInt64(collectionPath, propertyName)).Returns(valueToReturn); + mock.GetUInt64(collectionPath, propertyName).Returns(valueToReturn); } - Action verifyGet = (int callCount, string failMessage) => - mock.Verify(x => x.GetUInt64(collectionPath, propertyName), Times.Exactly(callCount), failMessage); - Action verifySet = (int callCount, ulong expectedValue, string failMessage) => - mock.Verify(x => x.SetUInt64(collectionPath, propertyName, expectedValue), Times.Exactly(callCount), failMessage); + Action verifyGet = (int callCount) => + mock.Received(callCount).GetUInt64(collectionPath, propertyName); + Action verifySet = (int callCount, ulong expectedValue) => + mock.Received(callCount).SetUInt64(collectionPath, propertyName, expectedValue); - SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock.Object, SetupSettingsStoreGet, verifyGet, verifySet, + SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock, SetupSettingsStoreGet, verifyGet, verifySet, defaultValueProperty, expectedDefaultValueInStore, expectedAlternateValueProperty, expectedAlternateValueInStore); } @@ -842,13 +839,14 @@ private void SettingStoreTest_MemoryStream(BaseOptionMod Action? overrideAssertEquality = null) where TOptMdl : BaseOptionModel, new() { - Mock mock = new(); - mock.Setup(x => x.CollectionExists(collectionPath)).Returns(true); - mock.Setup(x => x.PropertyExists(collectionPath, propertyName)).Returns(true); + WritableSettingsStore mock = Substitute.For(); + mock.CollectionExists(collectionPath).Returns(true); + mock.PropertyExists(collectionPath, propertyName).Returns(true); List setInvocations = new(); - mock.Setup(x => x.SetMemoryStream(collectionPath, propertyName, It.IsAny())).Callback((string _, string __, MemoryStream stream) => + mock.When((x) => x.SetMemoryStream(collectionPath, propertyName, Arg.Any())).Do((args) => { + MemoryStream stream = args.ArgAt(2); if (stream == null) setInvocations.Add(null); else @@ -857,15 +855,15 @@ private void SettingStoreTest_MemoryStream(BaseOptionMod void SetupSettingsStoreGet(byte[] valueToReturn) { - mock.Setup(x => x.GetMemoryStream(collectionPath, propertyName)).Returns(new MemoryStream(valueToReturn)); + mock.GetMemoryStream(collectionPath, propertyName).Returns(new MemoryStream(valueToReturn)); } - void VerifyGet(int callCount, string failMessage) + void VerifyGet(int callCount) { - mock.Verify(x => x.GetMemoryStream(collectionPath, propertyName), Times.Exactly(callCount), failMessage); + mock.Received(callCount).GetMemoryStream(collectionPath, propertyName); } - void VerifySet(int callCount, byte[] expectedValue, string because) + void VerifySet(int callCount, byte[] expectedValue) { int matchingCount = 0; foreach (byte[]? buffer in setInvocations) @@ -877,13 +875,13 @@ void VerifySet(int callCount, byte[] expectedValue, string because) else if (buffer.SequenceEqual(expectedValue)) matchingCount++; } - callCount.Should().Be(matchingCount, because); + callCount.Should().Be(matchingCount); } _output.WriteLine("expectedDefaultValueInStore (as string): {0}", System.Text.Encoding.UTF8.GetString(expectedDefaultValueInStore)); _output.WriteLine("expectedAlternateValueInStore (as string): {0}", System.Text.Encoding.UTF8.GetString(expectedAlternateValueInStore)); - SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock.Object, SetupSettingsStoreGet, VerifyGet, VerifySet, + SettingStoreTest(objUt, propertyUt, getProperty, setProperty, mock, SetupSettingsStoreGet, VerifyGet, VerifySet, defaultValueProperty, expectedDefaultValueInStore, expectedAlternateValueProperty, expectedAlternateValueInStore, overrideAssertEquality); } @@ -899,9 +897,9 @@ void VerifySet(int callCount, byte[] expectedValue, string because) /// Method to configure the settings store to return the provided value when the get method on the is /// called with the expected parameters. Signature is TStorageType valueToReturn /// Method to assert the settings store get method on the was - /// called. Signature is int expectedCallCount, string because. + /// called. Signature is int expectedCallCount. /// Method to assert the settings store set method on the was - /// called with the expected parameters. Signature is int expectedCallCount, TStorageType expectedValue, string because + /// called with the expected parameters. Signature is int expectedCallCount, TStorageType expectedValue /// Prior to test, the property will be set to this value using . /// This is the expected value of the property after Load returns when the setting store get /// method is configured to return . Must be different @@ -919,7 +917,7 @@ void VerifySet(int callCount, byte[] expectedValue, string because) /// Load operations rather than the standard assertions. Signature is TestValueType valueBeingTested, /// TPropertyType expected, TPropertyType actual, string because private void SettingStoreTest(BaseOptionModel objUt, PropertyInfo propertyUt, Func getProperty, Action setProperty, - WritableSettingsStore settingsStore, Action setupSettingsStoreGet, Action verifySettingsStoreGetWasCalled, Action verifySettingsStoreSetWasCalled, + WritableSettingsStore settingsStore, Action setupSettingsStoreGet, Action verifySettingsStoreGetWasCalled, Action verifySettingsStoreSetWasCalled, TPropertyType? defaultValueProperty, TStorageType expectedDefaultValueInStore, TPropertyType? expectedAlternateValueProperty, TStorageType expectedAlternateValueInStore, Action? overrideAssertEquality = null) @@ -941,7 +939,7 @@ private void SettingStoreTest(BaseOptionMo // Test save of default value bool saveMethodResult = uut.Save(objUt, settingsStore); - verifySettingsStoreSetWasCalled(1, expectedDefaultValueInStore, "because Save with the defaultValueProperty should result" + + VerifySet(1, expectedDefaultValueInStore, "because Save with the defaultValueProperty should result " + "in the settings store set method being called with expectedDefaultValueInStore"); saveMethodResult.Should().BeTrue("because we expect Save to return true for saving default value to store."); @@ -956,11 +954,11 @@ private void SettingStoreTest(BaseOptionMo else overrideAssertEquality(TestValueType.Alternate, expectedAlternateValueProperty, actualPropertyValue, propertyValueLoadMismatchBecause); loadMethodResult.Should().BeTrue("because we expect Load of the alternate value to report success when the property was successfully set."); - verifySettingsStoreGetWasCalled(1, "because the proper Settings Store Get method should be called during load for the alternate value."); + VerifyGet(1, "because the proper Settings Store Get method should be called during load for the alternate value."); // Test save process. Verify expected Settings Store Set method was called with proper value. saveMethodResult = uut.Save(objUt, settingsStore); - verifySettingsStoreSetWasCalled(1, expectedAlternateValueInStore, "because Save with the expectedAlternateValueProperty should result" + + VerifySet(1, expectedAlternateValueInStore, "because Save with the expectedAlternateValueProperty should result " + "in the settings store set method being called with expectedAlternateValueInStore"); saveMethodResult.Should().BeTrue("because we expect Save to return true for saving alternate value to store."); @@ -974,8 +972,32 @@ private void SettingStoreTest(BaseOptionMo actualPropertyValue.Should().BeEquivalentTo(defaultValueProperty, propertyValueLoadMismatchBecause); else overrideAssertEquality(TestValueType.Default, defaultValueProperty, actualPropertyValue, propertyValueLoadMismatchBecause); - verifySettingsStoreGetWasCalled(2, "because the proper Settings Store Get method should be called again during load for the default value."); + VerifyGet(2, "because the proper Settings Store Get method should be called again during load for the default value."); loadMethodResult.Should().BeTrue("because we expect Load of the default value to report success when the property was successfully set."); + + void VerifyGet(int expectedCallCount, string because) + { + try + { + verifySettingsStoreGetWasCalled(expectedCallCount); + } + catch (ReceivedCallsException ex) + { + throw new ReceivedCallsException($"{ex.Message} {because}", ex); + } + } + + void VerifySet(int expectedCallCount, TStorageType expectedValue, string because) + { + try + { + verifySettingsStoreSetWasCalled(expectedCallCount, expectedValue); + } + catch (ReceivedCallsException ex) + { + throw new ReceivedCallsException($"{ex.Message} {because}", ex); + } + } } #endregion Test Helper Methods and Main Test Method