How to unit-test a file writing method with Visual Studio's built-in automated tests? - visual-studio

I use Visual Studio 2008 Professional automated tests. I have a function that writes to a file. I want to unit test the file writing function. I have read somewhere that I would have to mock a file somehow. I don't know how to do it. Can you help?
How to unit-test a method that downloads a page from the Internet?

If the method has to open the file stream itself, then that's hard to mock. However, if you can pass a stream into the method, and make it write to that, then you can pass in a MemoryStream instead. An alternative overload can take fewer parameters, open the file and pass a FileStream to the other method.
This way you don't get complete coverage (unless you write a test or two which really does hit the disk) but most of your logic is in fully tested code, within the method taking a Stream parameter.

It depends how close your code is to the nuts'n'bolts; for example, you could work in Streams instead, and pass a MemoryStream to the code (and check the contents). You could just write to the file-system (in the temp area), check the contents and ditch it afterwards. Of if your code is a bit above the file system, you could write a mockable IFileSystem interface with the high-level methods you need (like WriteAllBytes / WriteAllText). It would be a pain to mock the streaming APIs, though.
For downloading from the internet (or pretending to)... you could (for example) write an IWebClient interface with the functions you need (like DownloadString, etc); mock it to return fixed content, and use something like WebClient as the basis for an actual implementation. Of course, you'll need to test the actual implementation against real sites.

If the goal of your test is to test that the file is actually created, it is an integration test, and not a unit test.
If the goal it to test that the proper things are writen into the file, hide the file access behind an interface, and provide an in memory implementation.
The same is true for web page access.
interface IFileService
{
Stream CreateFile(string filename);
}
class InMemoryFileService : IFileService
{
private Dictionary<string, MemoryStream> files = new Dictionary<string, MemoryStream>();
public Stream CreateFile(string filename)
{
MemoryStream stream = new MemoryStream();
files.Add(filename, stream);
return stream;
}
public MemoryStream GetFile(string filename)
{
return files[filename];
}
}
Using GetFile, you can find what should be written to disk.

You don't actually want to make the call to write the file directly in your function but instead wrap the file I/O inside a class with an interface.
You can then use something like Rhino Mocks to create a mock class implementing the interface.

Related

How to test external APIs?

I am having a hard time on how to start testing the integration with an external API ( Vimeo API ) for things like ( deleting a video - uploading a video - etc..).
Should I hit the real Vimeo's server while testing?
Is it a bad idea to do this like:
use Tests\TestCase;
use Vimeo\Laravel\VimeoManager;
class VimeoApiTest extends TestCase
{
protected function setUp() : void
{
parent::setUp();
$this->vimeo = new VimeoManager();
}
/** #test */
public function a_video_can_be_deleted()
{
$video = $this->vimeo->upload($fakeVideo);
// make http request to delete the video
$result = $this->vimeo->delete($video['id']);
$this->assertEquals('success', $result['status']);
}
}
In my eyes testing a package should not be your responsibility. Testing your implementation of the package is. Your example tests the package's VimeoManager directly. Which is in my opinion not what you should do.
Making a request to your API route that uploads the video is what you should test. During this test you do not want to upload it to the real Vimeo API, but you want to mock it.
Laravel includes a package that can do this, it is called Mockery. You can mock methods of classes to return a value without the initial logic being executed. In this case you would mock the delete method of the VimeoManager.
Laravel also provides so called Facades which can easily be mocked. I can see this package makes use of such facade. In this case you can do the following to test implemention of lets say your delete request.
/** #test */
use Vimeo\Laravel\Facades\Vimeo;
public function your_test()
{
Vimeo::shouldReceive('delete')
->once()
->with(...) // The parameters is should receive.
->andReturn(...); // The value it should return.
// Make the delete request to your API.
}
Well, you can test however you see fit. I've find it useful to have two types of tests.
A test which interacts with "something" else (service, system, etc...) is known as an integration test. These are nice and give some piece of mind, but are linked to the system that you are interacting with being online, this isn't always the case.
The second type of test can have a couple of different names, but that isn't really the point. The point of this second type of test is that you can "mock" out external/internal dependencies, ensuring that the "thing" your code depends on is online/behaves how you want. Mocking is when you manipulate a "thing" to respond a certain way. Usually, this is done via some framework or language feature. These types of test put a way larger burden on your code, and count more in my opinion.
I'm generally against mocking server to which my tests should be connected.
The main disadvantage of mocking servers and use simulators is fact that implementation of API may change (and for example throw exception/new status code or timeouts may be shorter) or there may be not compatibility between APIs between 2 versions of server.
Should I hit the real Vimeo's server while testing?
If You have possibility then create your local Vimeo's server using docker :)
Your tests will find out if something changes in API in future

Read and parse data from S3 PutRequest using Spring WebFlux

I have a stub setup to handle tests that interact with AWS S3 buckets. The (custom) stub implementation uses Spring WebFlux to respond to e.g. S3 put-requests.
Lately I have been forced to change my S3 implementation to use an InputStream rather than an actual file as input. My problem is now that my stub implementation doesn't yield the expected result when passing an InputStream rather than a file.
My stub is currently implemented like this:
RouterFunction<ServerResponse> putS3Object() {
return RouterFunctions.route(PUT("/S3/MyBucket/{filename}").and(accept(TEXT_PLAIN))) { ServerRequest request ->
return request.bodyToMono(String)
.doOnSuccess { s3Stubs.registerPutObject(request.pathVariable("filename"), it) }
.flatMap { response -> ServerResponse.ok().build() }
}
}
The String passed to s3Stubs.registerPutObject in the it parameter contains the expected value "Hello World".
Now, when I use an InputStream as argument to the S3 API instead of a file the it parameter is no longer "humanly readable". It contains data like: 18;chunk-signature=c27c7fa381b8aa2824e8487979d2d0e9ded04dd3 ..... 0;chunk-signature=db7e8b1bacc57da0d410ee116 - where I would have expected the same result "Hello World".
I'm unsure if this is related to my Webflux implementation or how S3 is handling InputStreams in comparison to actual files.
Using the exact same S3 implementation using InputStream works when putting to a real world S3 bucket...
Looking at the AWS S3 SDK, it seems that the InputStream variant is also requiring some metadata, which should contain the length and base64 hash of the content. This is probably what you're seeing here being sent to your stub.
bodyToMono(String.class) really buffers the whole request body in memory and decode that into a String. For other wire formats, Spring relies on Encoder and Decoder implementations (there's one for JSON, another one for protobuf). It is possible, but quite complex to write your own, and probably not the best choice when writing a stub implementation.
If you want to really stub this, you should either accept whatever the S3 client is sending you, or read up about the actual wire format used by that client.
Now about your current implementation: it seems you're trying to do I/O operations within a doOnXYZ method. Those methods are called "side-effect" methods, since their goal is to print some logs or record some state, but not do I/O-related work - and definitely not blocking I/O. Reactor offers ways to wrap blocking code for that.

Visual Studio: capture object state in debug mode and use it in unit test

Is there an easy and elegant way to capture objects in debug mode and just dump them in the unit tests?
I am using some very large object (like 30+ fields) and i would need that as data in my unit tests.
I don't know of any quick-and-easy way of doing this and, in fact, I suspect that the whole issue with field/properties, nesting, private-public prevents VS from providing a general-purpose solution for this.
You could certainly use serialization, for example calling some {{MyHelper.ToInitExpression()}} in the Immediate window while debugging and then taking the clipboard data and putting it into your unit tests. To make the initialization expression you would need to use reflection to find out what properties/fields there are and what their current values are. If you have nested objects, you'll need to take care of those too.
An alternative, if you go the ReSharper route, is to generate some sort of ToInit() method. You would need to make these individually for each of the classes you need. This is rather easy using ReSharper's generator infrastructure. Feel free to ping me (skype:dmitri.nesteruk) if you need help with this.
The other alternative is to simply hand-craft such methods, for example:
public static string ToAssemblyCode(this DateTime self)
{
var sb = new StringBuilder("new System.DateTime(");
sb.AppendFormat("{0},{1},{2}", self.Year, self.Month, self.Day);
if (self.Hour != 0 || self.Minute != 0 || self.Second != 0)
sb.AppendFormat(",{0},{1},{2}", self.Hour, self.Minute, self.Second);
if (self.Millisecond != 0)
sb.AppendFormat(",{0}", self.Millisecond);
sb.Append(")");
return sb.ToString();
}
You can try use IntelliDebugger plugin for Visaul Studio to create snapshot of any variable during debugging. The IntelliDebugger allows you to save and then to compare object with other objects of same type.
Desired object is stored in XML-format on disk (<YourSolution>\_IntelliDebugger.<YourSolution>\ExpressionSnapshots folder). I designed this feature to compare the state of objects during debugging. Perhaps it will be useful for writing unit-test or we can improve it for this case.
Note: IntelliDebugger is currently in beta and have limitations. We are open to any questions and feature requests to make it more effective for you.

How Would One Unit Test an HtmlHelper Which Actually Uses the helper in the Extension Method

I've spent the better half of this afternoon trying to figure out how to mock (using MOQ) up the relevant bits and pieces to unit test the following HtmlHelper, which users the UrlHelper class to create img tags:
public static IHtmlString Image(this HtmlHelper helper, string id, string url, string alternateText, object htmlAttributes)
{
// Instantiate a UrlHelper
var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
// Create tag builder
var builder = new TagBuilder("img");
// Create valid id
builder.GenerateId(id);
// Add attributes
builder.MergeAttribute("src", urlHelper.Content(url));
builder.MergeAttribute("alt", alternateText);
builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
// Render tag
return new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing));
}
Has anyone solved this problem already in their work?
You should test the end result. If you know that you helper should rerurn something like, lets say:
<img src="test.jpg" id="testId" alt="something" />
Then your Assertion should be by comparing this string against the actual result. You should not care whether it is using helper internally itself or not.
When I run into .NET types which are not unit test friendly I usually write my own interface (with only the methods that I need) and a shim class implementing the interface which just forwards method/property calls to the original class. The shim is testable by inspection.
Then I write all of the code that I need to unit test against this interface (so I depend on abstractions, not concretions). This includes extension methods, which extend the interface rather than the original concrete type. In this respect, testing extension methods is as easy as new Mock<IHtmlHelper>() ... - you can make IHtmlHelper do anything you like because you have total control of its behaviour in your unit tests.
Typing out the interface and the shim is a little bit tedious for classes with larger interfaces, but mostly I find the overhead is very low. It also means that I end up doing fewer weird tricks to make things testable, so my code is more consistent and easy to follow (dependencies are always injected the same way, tests are always written the same way).
I think the point that Husein Roncevic is making is that you should be testing the clients of HtmlHelper in terms of observable state rather than behaviour. In other words, the unit tests for the client code should not be aware of which methods were called (extension methods or otherwise). It sounds like you want to unit test the extension method itself, which is a perfectly reasonable thing to do.

Unit Testing File I/O Methods

I am still relatively new to unit testing. I have written a class in Ruby that takes a file, searches through that file for a given Regex pattern, replaces it, then saves the changes back to the file. I want to be able to write unit tests for this method, but I don't know how I would go about doing that. Can somebody tell me how we unit test methods that deal with file i/o?
Check out this How do I unit-test saving file to the disk?
Basically the idea is the same, the FileSystem is a dependency for your class. So introduce a Role/interface that can be mocked in your unit-tests (such that you have no dependency while unit-testing); the methods in the role should be all the stuff you need from the FileSystem -
Read() # returns file_contents as a string or string[]
Write(file_contents) # same as above
Now you can use a mock to return a canned string array - your class can then process this array. In production code, the real implementation of the role would hit the filesystem to return the array of lines.
You could create a file with known contents, do your replacement method, and then validate the contents of the modified file with the desired result.
I'd suggest using temporary files http://ruby-doc.org/core/classes/Tempfile.html for each run, and have a good read at unit testing framework http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html
If you are passing a file object to your method; try creating a dummy file object, use some i/o data streams to add contents to the file object and pass it to the method being tested.
If you are just passing the contents of the object using some datastream, create a dummy datasream and pass it to the method.
You can also opt to have a dummy file and create a file object from that file path and pass it to your method being tested.

Resources