patterncsharpMajor
Go on, mock my IDE
Viewed 0 times
mockidestackoverflow
Problem
Because of the coupling with the VBIDE API (the extensibility library for the VBA IDE), unit testing the rubberduck refactorings, inspections and quick-fixes has been pretty much impossible, at least until a
The
```
using System.Collections.Generic;
using System.Linq;
using Microsoft.Vbe.Interop;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Rubberduck.VBEditor;
using MockFactory = RubberduckTests.Mocks.MockFactory;
namespace RubberduckTests
{
public abstract class VbeTestBase
{
private Mock _ide;
private ICollection _projects;
[TestInitialize]
public void Initialize()
{
_ide = MockFactory.CreateVbeMock();
_ide.SetupProperty(m => m.ActiveCodePane);
_ide.SetupProperty(m => m.ActiveVBProject);
_ide.SetupGet(m => m.SelectedVBComponent).Returns(() => _ide.Object.ActiveCodePane.CodeModule.Parent);
_ide.SetupGet(m => m
MockFactory was implemented, to do things like this:internal static Mock CreateCodeModuleMock(string code)
{
var lines = code.Split(new[] {Environment.NewLine}, StringSplitOptions.None).ToList();
var codeModule = new Mock();
codeModule.SetupGet(c => c.CountOfLines).Returns(lines.Count);
codeModule.Setup(m => m.get_Lines(It.IsAny(), It.IsAny()))
.Returns((start, count) => String.Join(Environment.NewLine, lines.Skip(start - 1).Take(count)));
codeModule.Setup(m => m.ReplaceLine(It.IsAny(), It.IsAny()))
.Callback((index, str) => lines[index - 1] = str);
codeModule.Setup(m => m.DeleteLines(It.IsAny(), It.IsAny()))
.Callback((index, count) => lines.RemoveRange(index - 1, count));
codeModule.Setup(m => m.InsertLines(It.IsAny(), It.IsAny()))
.Callback((index, newLine) => lines.Insert(index - 1, newLine));
return codeModule;
}The
MockFactory is used extensively in an abstract class from which to derive all unit tests that need to work with the VBIDE API:```
using System.Collections.Generic;
using System.Linq;
using Microsoft.Vbe.Interop;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Rubberduck.VBEditor;
using MockFactory = RubberduckTests.Mocks.MockFactory;
namespace RubberduckTests
{
public abstract class VbeTestBase
{
private Mock _ide;
private ICollection _projects;
[TestInitialize]
public void Initialize()
{
_ide = MockFactory.CreateVbeMock();
_ide.SetupProperty(m => m.ActiveCodePane);
_ide.SetupProperty(m => m.ActiveVBProject);
_ide.SetupGet(m => m.SelectedVBComponent).Returns(() => _ide.Object.ActiveCodePane.CodeModule.Parent);
_ide.SetupGet(m => m
Solution
if (moduleName == null)
{
moduleName = componentType == vbext_ComponentType.vbext_ct_StdModule
? "Module1"
: componentType == vbext_ComponentType.vbext_ct_ClassModule
? "Class1"
: componentType == vbext_ComponentType.vbext_ct_MSForm
? "Form1"
: "Document1";
}Sorry, that I have to say this, but this is UGLY. Why don't you use a dictionary which is easily expandable if needed and would make the getting of the
moduleName more shining? If you don't want a dictionary, you really should extract it to a separate method where you simply should use a
switch instead of this ugly and unreadable ternary construct. Checking items for
null by using an if statement and if it is null assign a default value, so it can be handled nicer using the null coalescing operator ??. So for example this:
if (componentType == null)
{
componentType = vbext_ComponentType.vbext_ct_StdModule;
}would become this:
componentType = componentType ?? vbext_ComponentType.vbext_ct_StdModule;After a second glance at the
abstract class VbeTestBase I wonder why you decided to make this class abstract. You don't have neither abstract methods nor properties, hence there isn't any reason why this class should be abstract.Code Snippets
if (moduleName == null)
{
moduleName = componentType == vbext_ComponentType.vbext_ct_StdModule
? "Module1"
: componentType == vbext_ComponentType.vbext_ct_ClassModule
? "Class1"
: componentType == vbext_ComponentType.vbext_ct_MSForm
? "Form1"
: "Document1";
}if (componentType == null)
{
componentType = vbext_ComponentType.vbext_ct_StdModule;
}componentType = componentType ?? vbext_ComponentType.vbext_ct_StdModule;Context
StackExchange Code Review Q#96319, answer score: 20
Revisions (0)
No revisions yet.