I'm looking to learn how to correctly inject dependencies that come from the .NET Core library like StreamReader and FileStream. How do I inject these?
I have a class that reads in a file with a bunch of demographic census data, selects a random sampling of it, and then returns it as multiline string to its caller. It news up a FileStream to get access to a file's contents and then news up a StreamReader to read in the FileStream contents so I can manipulate the text. However, I'm looking to make this unit testable. If I needed to inject a class I created myself I'd generate an interface for the class to implement and pass that into the constructor, but this is a .NET Core type and there's no IFileStream, IStreamWriter, etc that I can inject. What would be the correct way to inject these so I can substitute in mocks during unit testing?
namespace MyNS.Lib
{
using System.IO;
using System.Text;
using PgpCore;
/// <summary>
/// A class for PGP encrypting strings.
/// </summary>
public class EncryptUtility
{
/// <summary>
/// Initializes a new instance of the <see cref="EncryptUtility"/> class.
/// </summary>
/// <param name="sampler">The CensusSampler needed by the class.</param>
public EncryptUtility(CensusSampler sampler)
{
Sampler = sampler;
}
/// <summary>
/// Encrypts a census file.
/// </summary>
/// <param name="censusFilePath">The path to the census file.</param>
/// <param name="keyPath">The path to the public key file.</param>
/// <returns>Returns an encrypted census file.</returns>
public string EncryptCensus(string censusFilePath, string keyPath)
{
using (FileStream census = new FileStream(censusFilePath, FileMode.Open))
{
var censusSr = new StreamReader(census);
var censusText = censusSr.ReadToEnd();
return EncryptString(censusText, keyPath);
}
}
}
}
I think what #devNull said probably makes the most sense. By encapsulating the portions of code that rely on things that don't make sense to inject and mock, I have kind of already separated out the parts of my code that need testing from parts that rely on the .NET Core runtime. I don't really need to test EncryptCensus because the only thing I'd be testing is that StreamReader works, which seems unnecessary. So I'll just test EncryptString. Thanks!
Related
I've got .ps1 scripts in my solution which added as .txt files into resources.
I use them in code this way:
string script = Properties.Resources.TRY_GET_GUEST_SCRIPT_SESSION_RESULT;
The problem is that I have no instruments to fast view content of this resource - the autogenerated function TRY_GET_GUEST_SCRIPT_SESSION_RESULT has only a brief annotation, in addition, has an uncomfortable 'comment' format:
/// <summary>
/// Looks up a localized string similar to Param(
/// [parameter(Mandatory=$true)]
/// [guid]
/// $SessionId
...[rest of string was truncated]"
/// </summary>
Which plugins, or code-tricks I can use to fast view (by press F12 - for ex.) resource?
When typing "///" above the method in Visual Studio, it generates XML summary.
For example:
/// <summary>
///
/// </summary>
/// <param name="par1"></param>
/// <param name="par2"></param>
/// <returns></returns>
public string Foo(int par1, string par2)
{
return "";
}
Is there a setting somewhere where I can stop adding the following line?
/// <returns></returns>
After some more research and several comments, I don't believe there is such setting or feature to customize the auto addition of
//<returns></returns>
This applies to VS2017 and earlier. Maybe this will be come a feature sometime in the future.
I'm using the current version of Sandcastle from Codeplex that is integrated with VS.NET 2012 to build a .cmh help file. The help file is being created, but I can't seem to ever get any of my <code> blocks to emit in the help file. I have the following easy example I keep working with:
/// <summary>
/// This is the summary
/// </summary>
/// <code>var s;</code>
public string SomeValue { get; set; }
When I look at the output .chm file, the var s; code is not present anywhere. I have done the following:
Added reference to Code Block Component in the Sandcastle project properties.
Tried making tag <code lang="C#">var s;</code> and <code language="C#">var s;</code> but neither made a difference.
Read documentation on the following sites detailing this process but to no avail:
https://www.simple-talk.com/dotnet/.net-tools/taming-sandcastle-a-.net-programmers-guide-to-documenting-your-code/
http://www.ewoodruff.us/shfbdocs/
The example is obviously a simplified version, but I'm just trying to get the basics work here. What am I doing incorrectly or missing?
I don't think the code tag is allowed to be by itself, try putting it inside an <example> tag, like <example><code>var s;</code></example>. So this should work:
/// <summary>
/// This is the summary
/// </summary>
/// <example>
/// <code>var s;</code>
/// </example>
public string SomeValue { get; set; }
Would you write xml-doc for a namespace? And if yes, how and where?
I would think, if it is possible, maybe an almost empty file like this:
/// <summary>
/// This namespace contains stuff
/// </summary>
namespace Some.Namespace
{
}
But will that work? Since you... "declare", or at least use the namespace in all the other files as well... and what would happen if you wrote an xml-documentation thing somewhere else on the same namespace? Would one be gone? Or would they be merged somehow?
NDoc supports this by recognising a special NamespaceDoc class located in each namespace, and using the documentation from that. I haven't tried it, but Sandcastle appears to support the same trick.
Edit:
For example:
namespace Some.Namespace
{
/// <summary>
/// This namespace contains stuff
/// </summary>
public static class NamespaceDoc
{
}
}
Sandcastle does not support the NamespaceDoc directly, but if you use Sandcastle Help File Builder you can use the NamespaceDoc class mentioned by Tim.
namespace Example
{
/// <summary>
/// <para>
/// Summary
/// </para>
/// </summary>
/// <include file='_Namespace.xml' path='Documentation/*' />
internal class NamespaceDoc
{
}
}
SCHB also extends the syntax slightly and allows embedding code examples straight from code files. An example _Namespace.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Documentation>
<summary>
<h1 class="heading">Example Namespace</h1>
<para>
This namespace is used in the following way:
</para>
<code source="Examples\Class.cs" lang="cs"></code>
<code source="Examples\Class.vb" lang="vbnet"></code>
<para>
Hopefully this helps!
</para>
</summary>
</Documentation>
Including documentation in XML file allows you to write short summary in code and larger description in a separate XML file for the help file. This way the code isn't cluttered with all the details and remains easily readable.
Sandcastle Help File Builder supports comments on namespaces. Open your Sandcastle project. In Project Properties window navigate to Summaries and click on the Edit Namespace Summaries button.
You can do it in doxygen using:
/// <summary>
/// description
/// </summary>
namespace name{};
Also, it's a good practice to declare your namespaces in a NameSpaces.cs file, and comment them only in this file.
If you use Sandcastle and its "Help File Builder" you can document namespaces and Namespace-Groups using the following Code in your Projects:
namespace Company.Product.Widgets
{
/// <summary>
/// These are the namespace comments for <c>Company.Product.Widgets</c>.
/// </summary>
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
class NamespaceDoc
{
}
}
If the project has namespace grouping enabled, you can also maintain the namespace group comments using a NamespaceGroupDoc class in a similar fashion. The following is an example:
namespace Company.Product
{
/// <summary>
/// These are the group comments for namespaces in <c>Company.Product</c>.
/// </summary>
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
class NamespaceGroupDoc
{
}
}
To keep the NamespaceDoc class from appearing in the help file, leave off the public keyword and mark it with a CompilerGenerated attribute.
For Reference see here: https://ewsoftware.github.io/SHFB/html/48f5a893-acde-4e50-8c17-72b83d9c3f9d.htm
It is not possible to put comments on namespaces.
UseNamespaceDocSummaries on http://ndoc.sourceforge.net/content/documenters.htm
If using Mono's mdoc documentation system, you can document namespace members by editing the ns-*.xml documentation files.
See the mdoc file format documentation for more details.
From a COM library (Microsoft Office Document Imaging aka MODI) I receive an image as an IPictureDisp which I would like to convert to a System.Drawing.Image object.
What would be the best way to do that?
Currently I'm using the code below, which however throws an NotImplementedException.
internal sealed class IPictureDispHost : AxHost
{
/// <summary>
/// Default Constructor, required by the framework.
/// </summary>
private IPictureDispHost() : base(string.Empty) { }
/// <summary>
/// Convert the image to an ipicturedisp.
/// </summary>
/// <param name="image">The image instance</param>
/// <returns>The picture dispatch object.</returns>
public new static object GetIPictureDispFromPicture(Image image)
{
return AxHost.GetIPictureDispFromPicture(image);
}
/// <summary>
/// Convert the dispatch interface into an image object.
/// </summary>
/// <param name="picture">The picture interface</param>
/// <returns>An image instance.</returns>
public new static Image GetPictureFromIPicture(object picture)
{
return AxHost.GetPictureFromIPicture(picture);
}
}
...
// somewhere later the conversion gets called
Image image = IPictureDispHost.GetPictureFromIPicture(picture);
This is the exception stack trace:
System.NotImplementedException: The method or operation is not implemented.
at System.Windows.Forms.UnsafeNativeMethods.IPicture.GetHandle()
at System.Windows.Forms.AxHost.GetPictureFromIPicture(Object picture)
at DocumentViewer.IPictureDispHost.GetPictureFromIPicture(Object picture)
I have references to stdole, System.Windows.Forms and System.Drawing in my project. Am I missing something?
Check out this article.
It describes three different options to take, just pick the one you find easiest or "cleanest" for your purposes (including the one you claim not to be working for you).
Olivier Jacot-Descombes: The link above is broken. I've added the corresponding link from the Internet Archive WayBackMachine:
Converting between IPictureDisp and System.Drawing.Image (MSDN Blogs > Andrew Whitechapel).
As it seems the picture obtained from the Microsoft Office Document Imaging COM components is not a valid IPictureDisp object and there seems no way to convert it.
Function GetImage(MyIPicture As stdole.IPictureDisp) As Drawing.Image
If CType(MyIPicture.Type, Integer) <> 1 then Throw New ArgumentException("Image not supported")
Return Drawing.Image.FromHbitmap(MyIPicture.Handle, MyIPicture.hPal)
End Function
Inspired from this post in the MSDN Forum.
No idea why the CType(MyIPicture.Type, Integer) = 1 is required, but it works..
Have you tried:
picture1.image = Microsoft.VisualBasic.Compatibility.VB6.Support.IPictureDispToImage(pict)
Microsoft.VisualBasic.Compatibility.VB6.Support.IPictureDispToImage is not guaranteed to always be included in future updates. So... taking the example from http://support.microsoft.com/kb/555417 I came up with the following
Example
Public Class ImageToPictureDispConverter
Inherits System.Windows.Forms.AxHost
Public Sub New()
MyBase.New("{63109182-966B-4e3c-A8B2-8BC4A88D221C}")
End Sub
Public Function GetImageFromIPictureDisp(ByVal objImage As stdole.IPictureDisp) As System.Drawing.Image
Dim objPicture As System.Drawing.Image
objPicture = CType(MyBase.GetPictureFromIPicture(objImage), System.Drawing.Image)
Return objPicture
End Function
End Class
I see in your constructor that you pass an empty string. I ended up having to pass the following string "{63109182-966B-4e3c-A8B2-8BC4A88D221C}". If I passed an empty string I received a system.formatexception error. It looks like you have everything I have except for this string in your call to base.
Hope this helps.