Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SLVS-1625 CaYC: Replace Moq with Nsubstitute #5836

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion SonarLint.VisualStudio.Integration.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,9 @@
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Async/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Mutable/@EntryIndexedValue">False</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNotificationDisabled/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Dpa/IsNoEtwHostNotificationEnabled/@EntryValue">False</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/Dpa/IsNoEtwHostNotificationEnabled/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002EMemberReordering_002EMigrations_002ECSharpFileLayoutPatternRemoveIsAttributeUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.UI;
[TestClass]
public class ProgressReporterViewModelTests
{
private ProgressReporterViewModel testSubject;
private ILogger logger;
private ProgressReporterViewModel testSubject;

[TestInitialize]
public void TestInitialize()
Expand Down
282 changes: 132 additions & 150 deletions src/Education.UnitTests/EducationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,163 +19,145 @@
*/

using System.Windows.Documents;
using Moq;
using NSubstitute.ReturnsExtensions;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Suppressions;
using SonarLint.VisualStudio.Education.Rule;
using SonarLint.VisualStudio.Education.XamlGenerator;
using SonarLint.VisualStudio.TestInfrastructure;

namespace SonarLint.VisualStudio.Education.UnitTests
namespace SonarLint.VisualStudio.Education.UnitTests;

[TestClass]
public class EducationTests
{
[TestClass]
public class EducationTests
private readonly SonarCompositeRuleId knownRule = new("repoKey", "ruleKey");
private readonly SonarCompositeRuleId unknownRule = new("known", "xxx");
gabriela-trutan-sonarsource marked this conversation as resolved.
Show resolved Hide resolved

private ILogger logger;
private IRuleHelpToolWindow ruleDescriptionToolWindow;
private IRuleHelpXamlBuilder ruleHelpXamlBuilder;
private IRuleInfo ruleInfo;
private IRuleMetaDataProvider ruleMetadataProvider;
private IShowRuleInBrowser showRuleInBrowser;
private Education testSubject;
private IThreadHandling threadHandling;
private IToolWindowService toolWindowService;

[TestInitialize]
public void TestInitialize()
{
toolWindowService = Substitute.For<IToolWindowService>();
ruleMetadataProvider = Substitute.For<IRuleMetaDataProvider>();
showRuleInBrowser = Substitute.For<IShowRuleInBrowser>();
ruleHelpXamlBuilder = Substitute.For<IRuleHelpXamlBuilder>();
ruleDescriptionToolWindow = Substitute.For<IRuleHelpToolWindow>();
ruleInfo = Substitute.For<IRuleInfo>();
logger = new TestLogger(true);
threadHandling = new NoOpThreadHandler();
SetupKnownRule();
SetupUnknownRule();

testSubject = new Education(toolWindowService, ruleMetadataProvider, showRuleInBrowser, logger, ruleHelpXamlBuilder, threadHandling);
}

[TestMethod]
public void MefCtor_CheckIsExported() =>
MefTestHelpers.CheckTypeCanBeImported<Education, IEducation>(
MefTestHelpers.CreateExport<IToolWindowService>(),
MefTestHelpers.CreateExport<IRuleMetaDataProvider>(),
MefTestHelpers.CreateExport<IShowRuleInBrowser>(),
MefTestHelpers.CreateExport<IRuleHelpXamlBuilder>(),
MefTestHelpers.CreateExport<ILogger>());

[TestMethod]
public void Ctor_IsFreeThreaded()
{
toolWindowService.ReceivedCalls().Should().HaveCount(0);
ruleMetadataProvider.ReceivedCalls().Should().HaveCount(0);
showRuleInBrowser.ReceivedCalls().Should().HaveCount(0);
ruleHelpXamlBuilder.ReceivedCalls().Should().HaveCount(0);
}

[TestMethod]
public void ShowRuleHelp_KnownRule_DocumentIsDisplayedInToolWindow()
{
var flowDocument = MockFlowDocument();
toolWindowService.GetToolWindow<RuleHelpToolWindow, IRuleHelpToolWindow>().Returns(ruleDescriptionToolWindow);

testSubject.ShowRuleHelp(knownRule, null, null);

VerifyGetsRuleInfoForCorrectRuleId(knownRule);
VerifyRuleIsDisplayedInIde(flowDocument);
VerifyRuleNotShownInBrowser();
}

[TestMethod]
public void ShowRuleHelp_FailedToDisplayRule_RuleIsShownInBrowser()
{
ruleHelpXamlBuilder.When(x => x.Create(ruleInfo, /* todo by SLVS-1630 */ null)).Do(x => throw new Exception("some layout error"));

testSubject.ShowRuleHelp(knownRule, null, /* todo by SLVS-1630 */ null);

VerifyGetsRuleInfoForCorrectRuleId(knownRule);
VerifyRuleShownInBrowser(knownRule);
VerifyAttemptsToBuildRuleButFails();
}

[TestMethod]
public void ShowRuleHelp_UnknownRule_RuleIsShownInBrowser()
{
testSubject.ShowRuleHelp(unknownRule, null, /* todo by SLVS-1630 */ null);

VerifyGetsRuleInfoForCorrectRuleId(unknownRule);
VerifyRuleShownInBrowser(unknownRule);
VerifyNotAttemptsBuildRule();
}

[TestMethod]
public void ShowRuleHelp_FilterableIssueProvided_CallsGetRuleInfoForIssue()
{
var issueId = Guid.NewGuid();

testSubject.ShowRuleHelp(knownRule, issueId, null);

ruleMetadataProvider.Received(1).GetRuleInfoAsync(knownRule, issueId);
}

private void VerifyGetsRuleInfoForCorrectRuleId(SonarCompositeRuleId ruleId) => ruleMetadataProvider.Received(1).GetRuleInfoAsync(ruleId, Arg.Any<Guid?>());

private void VerifyRuleShownInBrowser(SonarCompositeRuleId ruleId) => showRuleInBrowser.Received(1).ShowRuleDescription(ruleId);

private void VerifyRuleNotShownInBrowser() => showRuleInBrowser.ReceivedCalls().Should().HaveCount(0);

private void VerifyToolWindowShown() => toolWindowService.Received(1).Show(RuleHelpToolWindow.ToolWindowId);

private void VerifyAttemptsToBuildRuleButFails()
{
[TestMethod]
public void MefCtor_CheckIsExported()
{
MefTestHelpers.CheckTypeCanBeImported<Education, IEducation>(
MefTestHelpers.CreateExport<IToolWindowService>(),
MefTestHelpers.CreateExport<IRuleMetaDataProvider>(),
MefTestHelpers.CreateExport<IShowRuleInBrowser>(),
MefTestHelpers.CreateExport<IRuleHelpXamlBuilder>(),
MefTestHelpers.CreateExport<ILogger>());
}
ruleHelpXamlBuilder.ReceivedCalls().Should().HaveCount(1);
toolWindowService.ReceivedCalls().Should().HaveCount(1);
}

private void VerifyNotAttemptsBuildRule()
{
ruleHelpXamlBuilder.ReceivedCalls().Should().HaveCount(0);
toolWindowService.ReceivedCalls().Should().HaveCount(0);
}

private void VerifyRuleIsDisplayedInIde(FlowDocument flowDocument)
{
ruleHelpXamlBuilder.Received(1).Create(ruleInfo, /* todo by SLVS-1630 */ null);
ruleDescriptionToolWindow.Received(1).UpdateContent(flowDocument);
VerifyToolWindowShown();
}

private void SetupKnownRule() => ruleMetadataProvider.GetRuleInfoAsync(knownRule, Arg.Any<Guid?>()).Returns(ruleInfo);

[TestMethod]
public void ShowRuleHelp_KnownRule_DocumentIsDisplayedInToolWindow()
{
var ruleMetaDataProvider = new Mock<IRuleMetaDataProvider>();
var ruleId = new SonarCompositeRuleId("repoKey", "ruleKey");

var ruleInfo = Mock.Of<IRuleInfo>();
ruleMetaDataProvider.Setup(x => x.GetRuleInfoAsync(It.IsAny<SonarCompositeRuleId>(), It.IsAny<Guid?>())).ReturnsAsync(ruleInfo);

var flowDocument = Mock.Of<FlowDocument>();
var ruleHelpXamlBuilder = new Mock<IRuleHelpXamlBuilder>();
ruleHelpXamlBuilder.Setup(x => x.Create(ruleInfo, /* todo by SLVS-1630 */ null)).Returns(flowDocument);

var ruleDescriptionToolWindow = new Mock<IRuleHelpToolWindow>();

var toolWindowService = new Mock<IToolWindowService>();
toolWindowService.Setup(x => x.GetToolWindow<RuleHelpToolWindow, IRuleHelpToolWindow>()).Returns(ruleDescriptionToolWindow.Object);

var showRuleInBrowser = new Mock<IShowRuleInBrowser>();
var testSubject = CreateEducation(toolWindowService.Object,
ruleMetaDataProvider.Object,
showRuleInBrowser.Object,
ruleHelpXamlBuilder.Object);

// Sanity check - tool window not yet fetched
toolWindowService.Invocations.Should().HaveCount(0);

// Act
testSubject.ShowRuleHelp(ruleId, null, null);

ruleMetaDataProvider.Verify(x => x.GetRuleInfoAsync(ruleId, It.IsAny<Guid?>()), Times.Once);
ruleHelpXamlBuilder.Verify(x => x.Create(ruleInfo, /* todo by SLVS-1630 */ null), Times.Once);
ruleDescriptionToolWindow.Verify(x => x.UpdateContent(flowDocument), Times.Once);
toolWindowService.Verify(x => x.Show(RuleHelpToolWindow.ToolWindowId), Times.Once);

showRuleInBrowser.Invocations.Should().HaveCount(0);
}

[TestMethod]
public void ShowRuleHelp_FailedToDisplayRule_RuleIsShownInBrowser()
{
var toolWindowService = new Mock<IToolWindowService>();
var ruleMetadataProvider = new Mock<IRuleMetaDataProvider>();
var ruleHelpXamlBuilder = new Mock<IRuleHelpXamlBuilder>();
var showRuleInBrowser = new Mock<IShowRuleInBrowser>();

var ruleId = new SonarCompositeRuleId("repoKey", "ruleKey");

var ruleInfo = Mock.Of<IRuleInfo>();
ruleMetadataProvider.Setup(x => x.GetRuleInfoAsync(It.IsAny<SonarCompositeRuleId>(), It.IsAny<Guid?>())).ReturnsAsync(ruleInfo);

ruleHelpXamlBuilder.Setup(x => x.Create(ruleInfo, /* todo by SLVS-1630 */ null)).Throws(new Exception("some layout error"));

var testSubject = CreateEducation(
toolWindowService.Object,
ruleMetadataProvider.Object,
showRuleInBrowser.Object,
ruleHelpXamlBuilder.Object);

toolWindowService.Reset(); // Called in the constructor, so need to reset to clear the list of invocations

testSubject.ShowRuleHelp(ruleId, null, /* todo by SLVS-1630 */null);

ruleMetadataProvider.Verify(x => x.GetRuleInfoAsync(ruleId, It.IsAny<Guid?>()), Times.Once);
showRuleInBrowser.Verify(x => x.ShowRuleDescription(ruleId), Times.Once);

// should have attempted to build the rule, but failed
ruleHelpXamlBuilder.Invocations.Should().HaveCount(1);
toolWindowService.Invocations.Should().HaveCount(1);
}

[TestMethod]
public void ShowRuleHelp_UnknownRule_RuleIsShownInBrowser()
{
var toolWindowService = new Mock<IToolWindowService>();
var ruleMetadataProvider = new Mock<IRuleMetaDataProvider>();
var ruleHelpXamlBuilder = new Mock<IRuleHelpXamlBuilder>();
var showRuleInBrowser = new Mock<IShowRuleInBrowser>();

var unknownRule = new SonarCompositeRuleId("known", "xxx");
ruleMetadataProvider.Setup(x => x.GetRuleInfoAsync(unknownRule, It.IsAny<Guid?>())).ReturnsAsync((IRuleInfo)null);

var testSubject = CreateEducation(
toolWindowService.Object,
ruleMetadataProvider.Object,
showRuleInBrowser.Object,
ruleHelpXamlBuilder.Object);

toolWindowService.Reset(); // Called in the constructor, so need to reset to clear the list of invocations

testSubject.ShowRuleHelp(unknownRule, null, /* todo by SLVS-1630 */ null);

ruleMetadataProvider.Verify(x => x.GetRuleInfoAsync(unknownRule, It.IsAny<Guid?>()), Times.Once);
showRuleInBrowser.Verify(x => x.ShowRuleDescription(unknownRule), Times.Once);

// Should not have attempted to build the rule
ruleHelpXamlBuilder.Invocations.Should().HaveCount(0);
toolWindowService.Invocations.Should().HaveCount(0);
}

[TestMethod]
public void ShowRuleHelp_FilterableIssueProvided_CallsGetRuleInfoForIssue()
{
var toolWindowService = new Mock<IToolWindowService>();
var ruleMetadataProvider = new Mock<IRuleMetaDataProvider>();
var ruleHelpXamlBuilder = new Mock<IRuleHelpXamlBuilder>();
var showRuleInBrowser = new Mock<IShowRuleInBrowser>();
var issueId = Guid.NewGuid();
var ruleId = new SonarCompositeRuleId("repoKey", "ruleKey");
ruleMetadataProvider.Setup(x => x.GetRuleInfoAsync(ruleId, issueId)).ReturnsAsync((IRuleInfo)null);
var testSubject = CreateEducation(
toolWindowService.Object,
ruleMetadataProvider.Object,
showRuleInBrowser.Object,
ruleHelpXamlBuilder.Object);

testSubject.ShowRuleHelp(ruleId,issueId, null);

ruleMetadataProvider.Verify(x => x.GetRuleInfoAsync(ruleId, issueId), Times.Once);
}

private Education CreateEducation(IToolWindowService toolWindowService = null,
IRuleMetaDataProvider ruleMetadataProvider = null,
IShowRuleInBrowser showRuleInBrowser = null,
IRuleHelpXamlBuilder ruleHelpXamlBuilder = null)
{
toolWindowService ??= Mock.Of<IToolWindowService>();
ruleMetadataProvider ??= Mock.Of<IRuleMetaDataProvider>();
showRuleInBrowser ??= Mock.Of<IShowRuleInBrowser>();
ruleHelpXamlBuilder ??= Mock.Of<IRuleHelpXamlBuilder>();
var logger = new TestLogger(logToConsole: true);
var threadHandling = new NoOpThreadHandler();

return new Education(toolWindowService, ruleMetadataProvider, showRuleInBrowser, logger, ruleHelpXamlBuilder, threadHandling);
}
private void SetupUnknownRule() => ruleMetadataProvider.GetRuleInfoAsync(unknownRule, Arg.Any<Guid?>()).ReturnsNull();

private FlowDocument MockFlowDocument()
{
var flowDocument = Substitute.For<FlowDocument>();
ruleHelpXamlBuilder.Create(ruleInfo, /* todo by SLVS-1630 */ null).Returns(flowDocument);
return flowDocument;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,31 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using FluentAssertions;
using Microsoft.VisualStudio.Shell.TableControl;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Education.SonarLint.VisualStudio.Education.ErrorList;
using SonarLint.VisualStudio.Education.ErrorList;
using SonarLint.VisualStudio.Infrastructure.VS;
using SonarLint.VisualStudio.TestInfrastructure;

namespace SonarLint.VisualStudio.Education.UnitTests.ErrorList
namespace SonarLint.VisualStudio.Education.UnitTests.ErrorList;

[TestClass]
public class SonarErrorListEventProcessorProviderTests
{
[TestClass]
public class SonarErrorListEventProcessorProviderTests
{
[TestMethod]
public void MefCtor_CheckIsExported()
{
MefTestHelpers.CheckTypeCanBeImported<SonarErrorListEventProcessorProvider, ITableControlEventProcessorProvider>(
MefTestHelpers.CreateExport<IEducation>(),
MefTestHelpers.CreateExport<IErrorListHelper>(),
MefTestHelpers.CreateExport<ILogger>());
}
[TestMethod]
public void MefCtor_CheckIsExported() =>
MefTestHelpers.CheckTypeCanBeImported<SonarErrorListEventProcessorProvider, ITableControlEventProcessorProvider>(
MefTestHelpers.CreateExport<IEducation>(),
MefTestHelpers.CreateExport<IErrorListHelper>(),
MefTestHelpers.CreateExport<ILogger>());

[TestMethod]
public void Get_CreatesAndReturnsProcessor()
{
var testSubject = new SonarErrorListEventProcessorProvider(Mock.Of<IEducation>(), Mock.Of<IErrorListHelper>(), Mock.Of<ILogger>());
[TestMethod]
public void Get_CreatesAndReturnsProcessor()
{
var testSubject = new SonarErrorListEventProcessorProvider(Substitute.For<IEducation>(), Substitute.For<IErrorListHelper>(), Substitute.For<ILogger>());

var actual = testSubject.GetAssociatedEventProcessor(Mock.Of<IWpfTableControl>());
var actual = testSubject.GetAssociatedEventProcessor(Substitute.For<IWpfTableControl>());

actual.Should().NotBeNull();
}
actual.Should().NotBeNull();
}
}
Loading