I am trying to mock up the Win32 Registry objects in order to isolate some of my code for unit testing. I am able to create the shims and they get called to execute my code just fine. However I am not sure how to make the CreateSubKey method work. It needs to return a new RegistryKey object pointing to the newly created key. But I am having trouble figuring out how to do that. Here is what I have:
using (ShimsContext.Create())
{
Microsoft.Win32.Fakes.ShimRegistryKey.AllInstances.CreateSubKeyStringRegistryKeyPermissionCheck = (key, newSubkey, permissionCheck) =>
{
return key; // This returns the base, but I need a new one that adds the subkey...
};
}
What am I missing here?
Ok, I feel silly for not thinking of this before. Right after I posted, it hit me. I just need to make a new ShimRegistryKey.
using (ShimsContext.Create())
{
Microsoft.Win32.Fakes.ShimRegistryKey.AllInstances.CreateSubKeyStringRegistryKeyPermissionCheck = (key, newSubKeyName, permissionCheck) =>
{
var newSubKey = new Microsoft.Win32.Fakes.ShimRegistryKey();
newSubKey.NameGet = () => Path.Combine(key.Name, newSubKeyName); // All I care about for now is the name of the new subkey
return newSubKey;
};
}
Sometimes you just have to ask the question to see the answer. :-)
Related
I am using Ldapconnection.Sendrequest because I am running on Linux, so I can only use classes from the System.DirectoryServices.Protocols namespace.
The code works perfectly well against a live Active Directory, but here is an example anyway.
// retrieves the distinguishedname for all groups, starting from dc=test,dc=local
var request = new SearchRequest("dc=test,dc=local", "(Objectclass=group)", "distinguishedname");
var searchResponse = ldapConnection.SendRequest(request) as SearchResponse;
My question is, how can this be unit tested? I would like to unit test it because a different searchResponse will cause a different path to be taken through code.
I have tried mocking SearchResponse: (How to create an instance of SearchResponse class (which has no public constructors)?)
var ctors = typeof (SearchResponse).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
var neededCtor = ctors.First(
ctor =>
ctor.GetParameters().Count() == 5);
SearchResponse response = neededCtor.Invoke(new object[]
{
"distinguishedName",
null, // System.DirectoryServices.Protocols.DirectoryControl[]
null, // System.DirectoryServices.Protocols.ResultCode
errorMessage,
null // System.Uri[]
}) as SearchResponse;
return response;
But I cannot find a way to mock SearchResponse.Entries, as SearchResultEntryCollection and SearchResultEntry are (seemingly) unmockable. It's as though the dotnet team has gone out of its way to make this area completely unmockable.
I'm new to using LdapConnection (previously I could use the AccountManagement class, as I was running in Windows), so maybe I shouldn't be using LdapConnection in the first place?
Equally, I'd be open to running the AD tests in memory, as I would for database access, but I cannot find a way to do so.
Many thanks for you help,
Dan
I haven't find the way to make activitySource.StartActivity return non-null activity, which is different comparing to DiagnosticSource.StartActivity behavior. Is it expected? Am I'missing something obvious?
I can see docs says: "The created activity object, if it had active listeners, or null if it has no event listeners." The following test still fails, what's the correct way of initializing ActivityListener? The package I'm using is "System.Diagnostics.DiagnosticSource" Version="5.0.0".
[TestMethod]
public void Start_Not_Null_When_ActivityListener_Added_And_ShouldListenTo_Explicitly_Defined_Activity()
{
var activitySource = new ActivitySource("ActivitySourceName");
var activityListener = new ActivityListener
{
ShouldListenTo = s => true
};
ActivitySource.AddActivityListener(activityListener);
using var activity = activitySource.StartActivity($"MethodType:/Path");
Assert.IsNotNull(activity);
}
This test pass with the help from github:
[TestMethod]
public void Start_Not_Null_When_ActivityListener_Added_And_ShouldListenTo_Explicitly_Defined_Activity()
{
var activitySource = new ActivitySource("ActivitySourceName");
var activityListener = new ActivityListener
{
ShouldListenTo = s => true,
SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.AllData,
Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllData
};
ActivitySource.AddActivityListener(activityListener);
using var activity = activitySource.StartActivity("MethodType:/Path");
Assert.IsNotNull(activity);
}
The answer to this is you need to include a ActivitySamplingResult that's not set to None. The default appears to be none. MaGu's answer works because they set:
Sample = (ref ActivityCreationOptions activityOptions) => ActivitySamplingResult.AllData
The documentation for the method around StartActivity says it needs a listener but this is not the complete story you need an active listener that will do something with the activity. Setting the sample to None means it's effectively not in
I have a MVC4 web application I'm unit testing right now. It uses entity framework for the database portion. I'm using NSubstitute to mock the database. This code is basically copied and pasted from another site which works fine, so I hope I'm just missing something super simple.
Thanks in advance!
Applications table in SQL:
AppID | ApplicationName
----------------------------
1 | MyCoolApplication
2 | MyOtherApplication
Entity created the Application class:
public class Application
{
public int AppID { get; set; }
public string ApplicationName { get; set; }
}
The mock section of the unit test looks like this:
var mockDb = Substitute.For<MyCoolApplicationsEntities>();
var applications = new List<Application>
{
new Application {AppID = 1, ApplicationName = "MyCoolApplication"},
new Application {AppID = 2, ApplicationName = "MyOtherApplication"},
};
var mockApplicationSet = Substitute.For<IDbSet<Application>, DbSet<Application>>();
mockApplicationSet.Provider.Returns(applications.AsQueryable().Provider);
mockApplicationSet.Expression.Returns(applications.AsQueryable().Expression);
mockApplicationSet.ElementType.Returns(applications.AsQueryable().ElementType);
mockApplicationSet.GetEnumerator().Returns(applications.AsQueryable().GetEnumerator());
mockApplicationSet.When(q => q.Add(Arg.Any<Application>()))
.Do(q => applications.Add(q.Arg<Application>()));
mockApplicationSet.When(q => q.Remove(Arg.Any<Application>()))
.Do(q => applications.Remove(q.Arg<Application>()));
mockDb.Applications.Returns(mockApplicationSet); //This is the line creating the error
The full error is:
Test method
MyProjectName.Controllers.MyControllerTest.TestOfSectionImTesting
threw exception:
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException:
Could not find a call to return from.
Make sure you called Returns() after calling your substitute (for
example: mySub.SomeMethod().Returns(value)), and that you are not
configuring other substitutes within Returns() (for example, avoid
this: mySub.SomeMethod().Returns(ConfigOtherSub())).
If you substituted for a class rather than an interface, check that
the call to your substitute was on a virtual/abstract member. Return
values cannot be configured for non-virtual/non-abstract members.
Correct use:
mySub.SomeMethod().Returns(returnValue);
Potentially problematic use:
mySub.SomeMethod().Returns(ConfigOtherSub());
Instead try:
var returnValue = ConfigOtherSub();
mySub.SomeMethod().Returns(returnValue);
But that doesn't work in my environment because Applications isn't a method. Like I said, this works fine in another site of mine, so it's got to be something basic I'm missing. Nothing I've found online has been helpful with my particular case. I updated to the newest version of NSubstitute and I uninstalled/reinstalled, but still have got nothing.
Again, thanks in advance!
NSubstitute can not mock non-virtual members. (There are quite a few caveats to substituting for classes.)
MyCoolApplicationsEntities.Applications will need to be virtual for .Returns() to work.
Here's what ended up working:
var context = Substitute.For<MyCoolApplicationsEntities>();
var applications = new List<Application>
{
new Application {AppID = 1, ApplicationName = "MyCoolApplication"}
};
var mockApplications = Substitute.For<DbSet<Application>, IQueryable<Application>>();
((IQueryable<Application>)mockApplications).Provider.Returns(applications.AsQueryable().Provider);
((IQueryable<Application>)mockApplications).Expression.Returns(applications.AsQueryable().Expression);
((IQueryable<Application>)mockApplications).ElementType.Returns(applications.AsQueryable().ElementType);
((IQueryable<Application>)mockApplications).GetEnumerator().Returns(applications.AsQueryable().GetEnumerator());
mockApplications.When(q => q.Add(Arg.Any<Application>()))
.Do(q => applications.Add(q.Arg<Application>()));
mockApplications.When(q => q.Remove(Arg.Any<Application>()))
.Do(q => applications.Remove(q.Arg<Application>()));
context.Applications = mockApplications;
I can't see you classes but you need to create interfaces with virtual members and have your code call the class by the interface, then you will be able to mock out the class.
I was using this code, but I am getting a compiler warning that this method of creation is deprecated. As I want to remove the warning, and move to the newer version, I want to correct the code, but I can not get the CommandLineParser 1.9.7 library to work.
CommandLine.Parser OptionParser = new CommandLine.Parser(new CommandLine.ParserSettings
{
CaseSensitive = UseCaseSensitive,
IgnoreUnknownArguments = IgnoreUnknownOptions,
MutuallyExclusive = EnableMutuallyExclusive
}
);
bool Result = OptionParser.ParseArguments(Args, this);
This code works and Result would be True/False based on the parameters of the command line and options passed. However, the following warning is posted.
Warning 1 'CommandLine.Parser.Parser(CommandLine.ParserSettings)' is obsolete: 'Use constructor that accepts Action<ParserSettings>.'
The Online help shows this as an example for using the function.
new CommandLine.Parser(configuration: () => new CommandLine.ParserSettings(Console.Error))
I tried changing the code, but I am not getting the Lambda right, and am not sure how to get this to work. While the code executes, I only get the default functions, I can not seem to change the Case Sensitive, Mutually Exclusive, etc... options.
Line using the Constructor (from the inline IDE help)
bool Result = new CommandLine.Parser(configuration: (Settings) => new CommandLine.ParserSettings(UseCaseSensitive, EnableMutuallyExclusive, IgnoreUnknownOptions, null)).ParseArguments(Args, this);
Trying again with the virtual settings:
bool Result = new CommandLine.Parser(configuration: (Settings) => new CommandLine.ParserSettings
{
CaseSensitive = UseCaseSensitive,
IgnoreUnknownArguments = IgnoreUnknownOptions,
MutuallyExclusive = EnableMutuallyExclusive
}
).ParseArguments(Args, this);
The online help has not kept up with the tool, and I could use any pointers someone might have. Thanks in advance...
Looking at the source code the constructor runs that Action passed on new settings that it creates:
public Parser(Action<ParserSettings> configuration)
{
if (configuration == null) throw new ArgumentNullException("configuration");
this.settings = new ParserSettings();
configuration(this.settings);
this.settings.Consumed = true;
}
So in the Action<ParserSettings> you should set the values you want on the parameter, not create new settings (remember that an Action<T> is a prototype for a function that takes a T and does not return a value):
var parser = new CommandLine.Parser( s =>
{
s.CaseSensitive = UseCaseSensitive;
} );
NOTE: The source code I linked to does not appear to be the same version as you are using since Parser( ParserSettings ) is marked internal in the source I found, which means you wouldn't even be able to call it, and some of the ParserSettings properties do not appear in the version I found. However, I believe this answer applies to the version you have as well.
On my form I have a button click
private void button1_Click(object sender, EventArgs e)
{
do something
}
How on the click would I load my do something from a text file, for example my text file looks like this:
MessageBox.Show("hello");
label1.Text = "Hello";
on click it does everything in my text file, if possible.
Here is a very simple example, just to prove this is possible. Basically, you use CodeDomProvider to compile source at runtime, then execute using reflection.
var provider = CodeDomProvider.CreateProvider("C#");
string src=#"
namespace x
{
using System;
public class y
{
public void z()
{
Console.WriteLine(""hello world"");
}
}
}
";
var result = provider.CompileAssemblyFromSource(new CompilerParameters(), src);
if (result.Errors.Count == 0)
{
var type = result.CompiledAssembly.GetType("x.y");
var instance = Activator.CreateInstance(type);
type.GetMethod("z").Invoke(instance, null);
}
Edit
As #Agat points out, the OP seems to require a sort of scripting framework (it makes use of label1, a property of the current object), whereas my answer above obviously does not provide that. The best I can think of is a limited solution, which would be to require dependencies to be specified explicitly as parameters in the "script". Eg, write the scripted code like this:
string src = #"
namespace x
{
using System.Windows;
public class y
{
public void z(Label label1)
{
MessageBox.Show(""hello"");
label1.Text = ""Hello"";
}
}
}
";
Now you can have the caller examine the parameters, and pass them in from the current context, again using reflection:
var result = provider.CompileAssemblyFromSource(new CompilerParameters(), src);
if (result.Errors.Count == 0)
{
var type = result.CompiledAssembly.GetType("x.y");
var instance = Activator.CreateInstance(type);
var method = type.GetMethod("z");
var args = new List<object>();
// assume any parameters are properties/fields of the current object
foreach (var p in method.GetParameters())
{
var prop = this.GetType().GetProperty(p.Name);
var field = this.GetType().GetField(p.Name);
if (prop != null)
args.Add(prop.GetValue(this, null));
else if (field != null);
args.Add(field.GetValue(this));
else
throw new InvalidOperationException("Parameter " + p.Name + " is not found");
}
method.Invoke(instance, args.ToArray());
}
Like the other answers have stated, it isn't an easy thing to implement and can possibly be done through reflection depending on how advanced your scripts are.
But no one #BrankoDimitrijevic mentioned Roslyn and it is a great tool. http://msdn.microsoft.com/en-us/vstudio/roslyn.aspx
It hasn't been updated in quite awhile (Sept.2012) and doesn't have all of the features of C# implemented, however, it did have a lot of it implemented when I played around with this release.
By adding your assembly as a reference to the scripting session, you're able to gain access to all of your assembly's types and script against them. It also supports return values so you can return any data that a scripted method generates.
You can find what isn't implemented here.
Below is a quick and dirty example of Roslyn that I just wrote and tested. Should work right out of box after installing Roslyn from NuGet. The small bloat at the initialization of the script engine can easily be wrapped up in a helper class or method.
The key is passing in a HostObject. It can be anything. Once you do, your script will have full access to the properties. Notice that you just call the properties and not the host object in the script.
Basically, your host object will contain properties of the data you need for your script. Don't necessarily think of your host object as just a single data object, but rather a configuration.
public class MyHostObject
{
public string Value1 { get; set; }
public string Value2 { get; set; }
}
public class RoslynTest
{
public void Test()
{
var myHostObject = new MyHostObject
{
Value1 = "Testing Value 1",
Value2 = "This is Value 2"
};
var engine = new ScriptEngine();
var session = engine.CreateSession(myHostObject);
session.AddReference(myHostObject.GetType().Assembly.Location);
session.AddReference("System");
session.AddReference("System.Core");
session.ImportNamespace("System");
// "Execute" our method so we can call it.
session.Execute("public string UpdateHostObject() { Value1 = \"V1\"; Value2 = \"V2\"; return Value1 + Value2;}");
var s = session.Execute<string>("UpdateHostObject()");
//s will return "V1V2" and your instance of myHostObject was also changed.
}
}
No. You can not.
At least in any simple way.
The thing you want is something like eval('do something') from javascript.
That's not possible to do with C#. C# is a language which needs compilation before execution unlike javascript (for instance).
The only way to implement that is to build your own (pretty complicated as for beginner) parser and execute it in such way.
UPDATED:
Actually, as JDB fairly noticed, that's really not the only way. I love programming! There are so many ways to make a freakky (or even sometimes that really can be necessary for some custom interesting tasks (or even learning)!) code. he he
Another approach I've got in my mind is building some .cs file, then compiling it on-the-fly and working with it as some assembly or some other module. Right.