Mock void Method That Sets Private Setter in Implementations - c#

I have an interface that looks like this...
public interface ITempFileNameBuilder
{
string DirectoryPath { get; }
string FileName { get; }
void GenerateNewFileName();
}
... and I want to mock the GenerateNewFileName method so that it sets the FileName property to something new. I know this is an odd request because obviously there is no set defined in the interface because it's declared as private set; in the two implementations. I did that so you must call GenerateNewFileName to set the FileName property to something new.
Is this possible?
Edit
Here is the unit of work I'm trying to test.
public void StartRecording(string claimNo, string ip_no, string ip_name, IWaveIn input, Stream writer)
{
if (this.IsRecording)
{
return;
}
if (_input != null)
{
_input.Dispose();
}
_input = input;
_input.WaveFormat = _waveFormat;
_input.DataAvailable += (s, args) =>
{
_writer.Write(args.Buffer, 0, args.BytesRecorded);
byte[] buffer = args.Buffer;
for (int index = 0; index < args.BytesRecorded; index += 2)
{
short sample = (short)((buffer[index + 1] << 8) | buffer[index + 0]);
float sample32 = sample / 32768f;
_aggregator.Add(sample32);
}
OnDataAvailable(args);
};
_input.RecordingStopped += (s, args) =>
{
_input.Dispose();
_writer.Dispose();
OnRecordingStopped(args);
};
if (this.CurrentRecording != null)
{
_tempFileNameBuilder.GenerateNewFileName();
}
this.Recordings.Add(new RecordingTrack(claimNo, ip_no, ip_name,
_tempFileNameBuilder.FileName,
_recordingDeployer,
_recordingCompressor));
if (this.MicrophoneLevel == default(float))
{
this.MicrophoneLevel = .75f;
}
_aggregator.Reset();
_writer = writer;
_input.StartRecording();
this.IsRecording = true;
}
And the goal of this unit test is to ensure that the FileName of the CurrentRecording and LastRecording are in fact different. It's a regression test based on a bug we found earlier. The bug was happening because the FileName property on the RecordingTrack was not being set but rather was just returning the current FileName from the ITempFileNameBuilder instance and so the idea is to ensure that GenerateNewFileName was called and ensure that the set for the TempFileName on the recording track was called.
However, the set on the TempFileName on the RecordingTrack is private too, it's done in the constructor, so maybe this isn't really a unit test and more so an integration test?

You're mocking the interface, not the implementation. So you should care about how the caller interacts with this. If you expect them to call GenerateNewFileName() and then access FileName, just expect those two calls and give back the appropriate results (where the "generated" filename can just be anything).
There's no "field" to set here - you're just talking about an API.
Of course, you could easily create a fake instead of a mock, and use that instead.

In a case like this, you need to use an explicit private field instead of the implicitly-generated one in the property. You'll need to make sure that implementations define the get method for the FileName property in terms of that private field.

Related

Using one variable from a console in a windows form

I have this project:
And I need to use a variable that is in the "TransactionHandler.cs" in the "Enviar Faturas.cs" the TransactioHandler is a class library and the Enviar Faturas is a Windows Form.
Is it possible to do what I want? If so how should I do it?
UPDATE:
I have this variable declares in TransactionHandler.cs
var numfatura = _transaction.TransDocument + _transaction.TransSerial + _transaction.TransDocNumber;
And I need to use it on the Windows Form "Enviar Faturas".
UPDATE 2:
I have this code to select from a datagridview and write a textfile:
FileInfo arquivo = new FileInfo(#"C:\Users\HP8200\Desktop\faturas\" + r.Index + ".txt");
And I want to change the "r.index" for the variable I showed on the first update
I would suggest to use a property instead of a public field:
public class TransactionHandler
{
private static string numfatura = _transaction.TransDocument + _transaction.TransSerial + _transaction.TransDocNumber;
public static string Numfatura
{
get { return numfatura ; }
set { numfatura = value; }
}
}
From another class, you call your variable like this:
public class EnviarFaturas
{
public void DoSomething()
{
string r.Index= TransactionHandler.Numfatura;
}
}
Ok, from what I understand and having no idea of the execution flow you probably need something like this in the TransactionHandler (a property)
public int Numfatura
{
get
{
return this._transaction.TransDocument + this._transaction.TransSerial + this._transaction.TransDocNumber;
}
}
you can change the type to the one that stands behing the "var" in your code example.
To access it in the form you need an instance of the class (again I dont know what your logic is) but once you get it e.g.
var transactionHandler = new TransactionHandler();
you can simply try
r.Index = transactionHandler.Numfactura;
Keep in mind that you can hit the default data value (for int is 0) if your methods depend upon other event to happen.
I strongly suggest you to learn more about C# and Object Oriented Programming as Alexey Zimarev stated in the comments.
Also you should consider how to get/inject a concrete instance in the view.
Another good and related read will be singleton pattern, mvp and dependency injection.

How prevent this loop?

I cannot figure out how to fix this loop issue when i call a function like
new Common.Utility.Parameter().Get(Common.Constants.Parameter.SomeParameter);
Probably the error is caused by isHttpsCookie that recall the Parameter.Get()
Utility.cs
public static class Utility
{
public class Parameter
{
public string Get(string key)
{
string cookie = new Cookie().Read(key);
if (cookie == null)
{
var parameter = new Models.Parameter();
using (var db = new MyEntities())
parameter = db.Parameters.Where(w => w.Key == key).FirstOrDefault<Models.Parameter>();
if (parameter != null)
{
new Cookie().Write(key, parameter.Value);
return parameter.Value;
}
else
return string.Empty;
}
else
return cookie;
}
}
}
Cookie.cs
public class Cookie
{
private bool isHttpsCookie = Convert.ToBoolean(new Utility.Parameter().Get(Constants.Parameter.IsHttps)); // Loop here?
public string Read(string cookieName)
{
HttpCookie httpCookie = HttpContext.Current.Request.Cookies[HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.GetName().Na​me + "_" + cookieName];
return httpCookie != null ? HttpContext.Current.Server.HtmlEncode(httpCookie.Value).Trim() : string.Empty;
}
public void Write(string cookieName, string cookieValue, bool isHttpCookie = true)
{
if (isHttpsCookie)
isHttpCookie = false;
var aCookie = new HttpCookie(HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.G​etName().Name + "_" + cookieName)
{Value = cookieValue, Expires = Common.Constants.Cookie.DefaultExpires, HttpOnly = isHttpCookie};
HttpContext.Current.Response.Cookies.Add(aCookie);
}
}
Apparently, your code is falling into a sort of recursion where you suspect it is. What I'm having trouble with is why are you creating new objects just to call a single method. Looks like you could have them as static methods in your classes, so no object creation would be needed, thus no 'looping'.
Have a closer look at your Cookie.Write() and Parameter.Get() method, they are calling each other. When you declare isHttpsCookie, you call Parameter.Get(). In the Parameter.Get(), if the condition is valid, it will call to Cookie.Write(). In its turn, when you call new Cookie(), the isHttpsCookie is called again and it's continuing forever.
Another point at this code:
if (isHttpsCookie)
isHttpCookie = false;
do you try to say that isHttpsCookie should be false at all time? so why do you need to declare this?
Solution: Do like #Takeshi said: those methods can be declared as static so no class declaration is required to called them.
You are correct in what you suspect. the isHttpsCookie declaration is causing you grief.
When the Cookie object is created it goes away and executes the method get from your utility class which creates an instance of cookie. Therefor you have your recursion.
You will need to change the way you initialise isHttpsCookie. Maybe only initialise / check if you are doing a write. After all you are most likely going to read more often than write.
Hope that helps.

Adding a Non-Static Class to a static List

I have a Non Static class which contains a number of properties
private static List<FileClass> FileClassList = new List<FileClass>();
internal void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo)
{
this.FileID = FileIDCounter;
this.Name = finfo.Name;
this.FullName = finfo.FullName;
this.Attributes = GetFileAttributes(finfo);
this.CreationTime = finfo.CreationTime;
this.Extension = finfo.Extension;
this.isReadOnly = finfo.IsReadOnly;
this.LastAccessTime = finfo.LastAccessTime;
this.LastWriteTime = finfo.LastWriteTime;
this.Length = finfo.Length;
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(this);
if (FileClassFileAdded != null) FileClassFileAdded(this);
}
Although the Class is added FileClassList.Add(this); the final result is a FileClassList filled with whatever the last instance of the class contained and not the this.Properties values.
So, how do I add the current instance of the FileClass to the FileClassList so that the contents of the FileClassList contains the different instances of the FileClass.
Here is what your issue most likely is...
Having this:
internal void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo)
Somewhere you probably do:
MyClassWhichAddsAFile cls = new MyClassWhichAddsAFile();
cls.AddFile(fileInfo1);
cls.AddFile(fileInfo2);
cls.AddFile(fileInfo3);
While you need to do (under this design):
MyClassWhichAddsAFile cls1 = new MyClassWhichAddsAFile();
cls1.AddFile(fileInfo1);
MyClassWhichAddsAFile cls2 = new MyClassWhichAddsAFile();
cls2.AddFile(fileInfo2);
........
Again, I am not discussing your design here or how to do it right. I am telling you that your problem is probably comes out from this situation
I think you have your design slightly askew. I don't think that AddFile should be part of FileClassList rather.
However in leiu of not having another place to hold it. I'd say do this:
internal static void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo, FileClass theClass)
{
theClass.FileID = FileIDCounter;
theClass.Name = finfo.Name;
theClass.FullName = finfo.FullName;
theClass.Attributes = GetFileAttributes(finfo);
theClass.CreationTime = finfo.CreationTime;
theClass.Extension = finfo.Extension;
theClass.isReadOnly = finfo.IsReadOnly;
theClass.LastAccessTime = finfo.LastAccessTime;
theClass.LastWriteTime = finfo.LastWriteTime;
theClass.Length = finfo.Length;
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(theClass);
if (FileClassFileAdded != null) FileClassFileAdded(theClass);
}
A better approach would be to create a contrstuctor on FileClass that takes a FileInfo and fills these properties in and call it like this:
var someFileClass = new FileClass(theFileInfo);
FileClass.AddFile(someClassFile);
and AddFile would be:
internal static void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo, FileClass theClass)
{
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(theClass);
if (FileClassFileAdded != null) FileClassFileAdded(theClass);
}
even then I think the AddFile should be a method on the the caller not the callee!

Is it possible to execute C# code represented as string?

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.

How do I pass a string to a function requiring an Object?

I am using Chello (the c# wrapper for the Trello API). I need to pass the argument "createCard" as per the documentation here: https://trello.com/docs/api/card/index.html
And this is the function I am using from Chello:
public IEnumerable<CardUpdateAction> ForCard(string cardId, object args)
{
string queryString = BuildQueryString(args);
return GetRequest<List<CardUpdateAction>>("/cards/{0}/actions?{1}", cardId, queryString);
}
I have tried calling this in this way:
List<CardUpdateAction> cua = chello.CardUpdates.ForCard("5264d37736695b2821001d7a","createCard").ToList();
but I get the error: Parameter Count Mismatch
on this function:
protected static string BuildQueryString(object args)
{
string queryString = String.Empty;
if (args != null)
{
StringBuilder sb = new StringBuilder();
foreach (var prop in args.GetType().GetProperties())
{
sb.AppendFormat("{0}={1}&", prop.Name, prop.GetValue(args, null));
}
if (sb.Length > 0) sb.Remove(sb.Length - 1, 1);
queryString = sb.ToString();
}
return queryString;
}
The problem is the fact that your API you are using expects you to pass in a class that has public properties equal to the tags you want to use.
This is very easy to do using Anonymous Types (I am doing a slightly different example to help illustrate a point)
//This will cause BuildQueryString to return "actions=createCard&action_fields=data,type,date"
var options = new { actions = "createCard", action_fields = "data,type,date" };
List<CardUpdateAction> cua = chello.CardUpdates.ForCard("5264d37736695b2821001d7a",options).ToList();
string is an object. Every type in .NET platform inherits from Object. This is called Unified Type System.
On the other hand, we have the Liskov Substitution Principle, which put simply, says that if B is a subtype of A (B is A), then you should be able to use B, wherever A is used.
Based on these reasons, you can pass string to any method that accepts an object as an argument.
You can test it:
public void DoSomething(object args)
{
}
public void Main()
{
DoSomething("some string argument, instead of the object");
}
It works just fine. No error.

Categories

Resources