Decaying Code

Where code comes to die

About the author

Maxime Rouiller is a passionate .NET technology specialist, working for 7 years in large software development, advocating Agile and TDD. Aware of the latest technological trends, he intervenes as a specialist in the .NET Montréal usergroup and acts regularly as a speaker for Web Form programmers on the MVC platform.

View Maxime Rouiller's profile on LinkedIn

Month List

My baby steps to PostSharp 1.0

So... you downloaded PostSharp 1.0 and you installed it and are wondering... "What's next?".

Well my friends, let me walk you through the first steps of PostSharp. What could we do that would be simple enough? Hummm... what about writing to a debug window? That sounds simple enough! Let's start. So I created a new Console Application project and I added the reference to PostSharp.Laos and PostSharp.Public. As a requirement, the class must be tagged with "Serializable" attribute and implement OnMethodBoundaryAspect (not in all case but let's start small here).

Next, I have a few methods I can override. The two that we are interested in right now is "OnEnter" and "OnExit". Inside of it, we'll say which method we are entering and which one we are exiting. Here are my Guinea pig classes:

public class FooBar
        {
        [DebugTracer]
        public void DoFoo()
        {
        Debug.WriteLine("Doing Foo");
        }

        [DebugTracer]
        public void DoBar()
        {
        Debug.WriteLine("Doing Bar");
        }
        }

        [Serializable]
        [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
        public class DebugTracer : OnMethodBoundaryAspect
        {
        public override void OnEntry(MethodExecutionEventArgs eventArgs)
        {
        Debug.WriteLine(string.Format("Entering {0}", eventArgs.Method.Name));
        }

        public override void OnExit(MethodExecutionEventArgs eventArgs)
        {
        Debug.WriteLine(string.Format("Exiting {0}", eventArgs.Method.Name));
        }
        }

See how simple this is? But... does it work? Let's see the trace of calling each methods:

Entering DoFoo
Doing Foo
Exiting DoFoo
Entering DoBar
Doing Bar
Exiting DoBar

Isn't that wonderful? Compile execute and enjoy. But... what about the community you say? Of course if the tool is not open source there is probably nothing built around it, right? Wrong!

Here is a few resources for PostSharp that include pre-made attributes that are ready to be used:

That was everything I could find. Do you know any others?


Permalink | Comments (0) | Post RSSRSS comment feed

PostSharp - The best way to do AOP in .NET

Who knows about Aspect-Oriented Programming (AOP)? Common! Don't be shy! Ok, now lower your hands. My prediction is that a lot of you didn't raise their hands. So let's resume what AOP is:

Aspect-oriented programming is a programming paradigm that increases modularity by enabling improved separation of concerns. This entails breaking down a program into distinct parts (so called concerns, cohesive areas of functionality). [...]

So what does it mean truly? Well, it's a way to declare part of your software (methods, classes, assembly) to have a "concern" applied to them. What is a concern? Logging is one. Exception handling is another one. But... let's go wild... what about caching, impersonation, validation (null check, bound check), are all concerns. Do you mix them with your code? Right now... you are forced to do it.

The state of current AOP

Alright for those who raised their hands earlier, what are you using for your AOP concerns? If you are using patterns and practices Policy Injection module, well, you are probably not happy. First, all your objects need to be constructed by an object builder and need to inherit from MarshalByRefObject or implement an interface.

This is not the best way but it's been done in the "proper" way without hack.

What is PostSharp bringing?

PostSharp might be a "hack" if think so. Of course, it does require you to have it installed on your machine while compiling for it to work. But... what does PostSharp does exactly? It does what every AOP should do. Inject the code before and after the matching method at compile time. Not just PostSharp methods but any methods that is inherited from the base class PostSharp is ofering you. Imagine what you could do if you could tell the compiler to inject ANY code before/after your method on ANY code you compile. Think of the possibilities. I'll give you 2 minutes for all this information to sink in... (waiting)... got it? Start to see the possibility? All you need to do is put attributes on your methods/attributes like this:

[NotNullOrEmpty]
        public string Name { get; set; }

        [Minimum(0)]
        public int Age { get; set; }

Now look at that code and ask yourself what it do exactly. Shouldn't be hard. The properties won't allow any number under "0" to be inserted inside "Age" and "Name" will not allow any null or empty string. If there is any code that try to do that, it will throw a ValidationException.

Wanna try it?

Go download PostSharp immediatly and it's little friend ValidationAspects on Codeplex. After you have tried, try to build your own and start cleaning your code to achieve better readability.

And yes... both are Open-Source and can be used at no fee anywhere in your company.

Suggestion to CLR Team

Now, PostSharp force us to have it installed with the MSI for it to work because it needs to install a Post-Compile code injector (like some obfuscation tools). What would be really nice, is to be able to do the same thing built-in with the compiler. The compiler is already checking for some attribute already... I would love to have this "internal working" exposed to the public so that we can build better tools and, more importantly, better code.

UPDATE: I want to mention that PostSharp is NOT open-source. However is free unless you need to package it with your tool.


Permalink | Comments (0) | Post RSSRSS comment feed

LyricWiki.org - How to retrieve lyrics for your mp3 in C#?

I have an iPhone and I got a lot of songs on it. I don't particularly love to sing but I got a few bands that have tendencies to say their lyrics in a... obscure way. Since I'm really curious, I'm always on Google searching for the lyrics. I wanted to save some time and avoid unnecessary browsing. The iPhone have the capacity of displaying lyrics if they are included inside the mp3 metadata. Updating the lyrics is something but where will I retrieved thousands song lyric?

I recently found out about a website called LyricWiki.org. What is interesting is that they have a web service (for free) available. I then decided to share how I did it. First thing is to start a project. You will then add a service reference like this:

image

Click on Go, change namespace and click on OK. Once  this is done, the easy part is done. Please note that the service URL has been stored under App.config with all the related settings.

Now to retrieve the actual lyrics, no more than a little bit of code:

// create a client to connect to the service
        LyricWikiPortTypeClient client = new LyricWikiPortTypeClient();

        // retrieve a song. Creed is good. Love this band.
        LyricsResult song = client.getSong("Creed", "One");

        // display the artist and the lyrics
        Console.WriteLine(string.Format("Found lyrics for \"{0} - {1}\":\r\n\r\n" +
        "{2}", song.artist, song.song, song.lyrics));

        // let you read it :)
        Console.ReadLine();

That was easy now wasn't it? Next post, how to update your mp3 with iTunes! Keep reading!


Categories: c# | code snippet
Permalink | Comments (0) | Post RSSRSS comment feed

EntLib 4.0 - ExceptionPolicy.HandleException is not thread safe

We've faced this problem recently where Enterprise Library was crashing. Not everywhere... just on this little line of code. We were trying to save to a database asynchronously but if the database was not available, it threw an exception which Enterprise Library was supposed to catch.

However, this never happened. Enterprise library crashed on us. Mind you, we didn't figure out this problem until recently because the problem was just happening in production.

When we managed to reproduce the exception in a development environment (where debugging is possible), we got an error similar to "An item with the same key has already been added". Here's the beginning of the stack trace:

Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ExceptionHandlingException: The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ExceptionPolicyImpl, LogException]) failed: The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter, null]) failed: An item with the same key has already been added.

That lead me to this thread where it was mentioned that an issue was logged. I found this issue which mentioned concurrency issue. Since our code was multi-threaded, we had two options. Replace Enterprise Library 4.0 by Enterprise Library 4.1 or make a thread safe wrapper for the call to the log exception.

The first option required reconfiguring the build and all development machine, the second one consisted of coding a dirty patch. We went with the first one (what else did they fix in 4.1?) for obvious reason.

So, if you have this kind of problem with Enterprise Library 4.0, you might want to upgrade to Enterprise Library 4.1. Since the problem happen in the error handling section, it makes this kind of bug hard to understand and erratic (due to concurrency).


Categories: c# | enterprise library
Permalink | Comments (0) | Post RSSRSS comment feed

Find and Reproduce Heisenbugs - CHESS is the tool for you

Microsoft is mainly known for 2 things. Windows and Office. However, for programmers,  Microsoft is also know for many more projects/product like .NET, Enterprise Library, ASP.NET MVC, Team Foundation Server, SharePoint, etc.

Among the few tools that are not really known and publicised at the moment are the projects inside Microsoft Research. This is the land of Beta or "software-never-to-be-released". Either the project is too crazy(read: inovative?) or not useful for people at the time. But there is time where a tool stands out and need to be  talked about.

My friend Eric De Carufel recently talked to me about this tool called CHESS from Microsoft Research. He tested it and it allows for testing for those rare bugs that are only found when there is enough concurrency. Those bugs were tested before with stress test. Stress test are not supposed to be used for finding concurrency bugs but they are traditionally used for that too because when a system is under stress, concurrency happens.

CHESS is there to solve this problem. It includes itself among your unit test and try every possible permutation of code that happens asynchronously. This include race condition, dead lock, and what else exists (not an expert in multi-threaded applications).

Of course, I expect Eric to blog more about this amazing software that is coming from Microsoft's Trenches.

Want more information? Get on the CHESS website. If you want to find more interesting projects that Microsoft's genius are working on, visit Microsoft Research.


Categories: c# | research | software | unit test
Permalink | Comments (0) | Post RSSRSS comment feed

Adding lyrics to your MP3 via iTunes

I found tonight an interesting site that built an application that insert the lyrics inside your mp3 collection.

It requires iTunes and the .NET framework.

It can be found here. I will rewrite the application in C#, improve the source and contact the author if we can put it in Google Code or Codeplex.

Enjoy!


Categories: c# | software
Permalink | Comments (0) | Post RSSRSS comment feed

5 reasons why you should use ASP.NET MVC

I'll be fair with you readers. I've only toyed with the ASP.NET MVC framework. It looks great as of now but it's the first full blown MVC framework that we have that is backed by Microsoft. However, there is a lot of opposition nowadays that tend to be formulated like this:

Why should I use ASP.NET MVC? WebForms works well.

Other problems come from the lack of server controls. When a developer look at that and he then wonder why he should have to write HTML and Javascript when before he could have retrieved all that beautiful information with a simple postback.

So without ranting any further, here is 5 reasons why you should use ASP.NET MVC.

1. Testability

When the MVC model is properly applied, it allow for a better separation of your business logic and your presentation code. If the view is not included inside your model, you can easily test without requiring a web server. By default, when starting a new MVC project, Visual Studio offer to create a new Unit Test project based on Microsoft's Unit Test framework. Other Unit tests framework can also be configured to be used by default instead of Microsoft's solution.

The way the code is also made, the controller is the one handling the calls from the route. They can be instantiated outside of a web request which makes them easy to test too.

2. Perfect control of the URLs

ASP.NET MVC use URL Routing to better control the request and forward them to your controllers. Instead of 1 to 1 mapping, they allow pattern matching. The default being "{controller}/{action}/{id}" with the default being "Home/Index". This technically allow you to set the URLs exactly how you want. You don't have to create folder for every level deep it goes. The URL routing allows you to make clean URL that will be easy to remember.

Would you rather try to remember http://localhost/Sales/DisplayProduct.aspx?ProductID=23213 or http://localhost/Product/Detail/23213 ? Even better, if you are an e-Commerce site and want some fast link.... you can directly bind those URL to http://localhost/23213 to make it more easy to remember. Doing that in WebForm while keeping all this unit testable would just be too time consuming now is it?

3. Better Mobility Support

In WebForm, you would have to detect on each page that the browser is a mobile and adapt your rendering for the mobile on each and every form. You could also redirect the user to different page when it's a mobile. What is excellent with MVC is that it's not the view that is receiving the request. It's the controller. The controller can then dynamically decide which view to render while keeping the same URL. So to see a product view, you don't even need to send different URL to different provider. You just detect which device you are handling and redirect it to the proper view. As you support more and more mobile device, you can keep on adding view that are more specific to each device. Want to support this new HTC? Create a view, detect the browser and ensure the right view is displayed. Want to support some iPhone goodness with some device specific HTML? Create the necessary view, reuse the browser detection and display the view.

You can keep on doing that ad infinitum and as much as you want depending on your audience. Having Mobile support now is more convenient than it has ever been.

4. View Engines

Now if you only built ASP.NET WebForms, this term might be weird for you. Let's just say that you have been using the same view engine all this time without wondering if you could choose. The WebForm view engine is... well... what you have been using all this time. This includes server tags (<% %>), binding tags (<%# %>) as well as control tag (<asp:TextBox ... />).

The Spark Engine is a good example. MvcContrib also offer 4 different view engine (Brail, NHaml, NVelocity, XSLT). Each of those engine are created to fix some specific problems. Different view engines can be used on different view. One page could be handled with WebForm view engine, one with Spark Engine, one with XSLT, etc. Different view, different problem different solution.

You might not have to use those, but the simple fact that they are available will make your life easier if they are needed.

5. Built-in and shipped jQuery support

Let's keep the best for the end. jQuery is shipped with any new project instance of ASP.NET MVC. Since Microsoft announced support for jQuery, it's been the big buzz in the javascript world. Since ASP.NET MVC don't rely on Postback, a strong javascript framework is needed to provide for all the UI the previous server control were offering. jQuery easily offer you AJAX, DOM manipulation, event binding and  this across browser.

Of course, jQuery is not an advance to MVC itself. But it is a serious offering from ASP.NET MVC. No more download or "I'll write my own" stuff. I don't know for all of you but if I have to do javascript, I normally do a document.getElementById. This will work in most browsers but as soon as you start going funky, some browser will misbehave. jQuery simply allow you to write $("#myControlId") or many more shortcuts to simply do what you need across browsers. Just by having jQuery available stops me from writing incompatible code.

Conclusions

Lots of point goes toward MVC. Way more could be added. You certainly don't want to miss Kazi Manzur Rashid's blog about ASP.NET MVC Best Practices (part 1, part 2). Scott Hanselman, Phil Haack also have great posts about ASP.NET MVC.

Don't be fooled. Web Forms are not necessarly evil. They just aren't leading you to a pit of success.


Categories: architecture | asp.net | c# | mvc | unit test
Permalink | Comments (11) | Post RSSRSS comment feed

System.Diagnostics.Process and xcopy... why it doesn't work?

We spent 30 minutes on a spiny issue. We execute some commands directly from a C# program but we want to make sure that everything executed. We did unit test on some code and everything seemed to work.

Today, we tried it live with some real case scenario where we execute some XCOPY. And then.... nothing.

We didn't receive any ExitCode that was 0. We didn't catch any exception. And we didn't catch anything in the error stream.

Here is the code that we used:

private void ExecuteProcess()
        {
        // setup the process info
        var startInfo = new ProcessStartInfo(@"cmd.exe", @" /c xcopy c:\file*.txt c:\file*.bck")
        {
        UseShellExecute = false,
        CreateNoWindow = true,
        WorkingDirectory = @"C:\",
        RedirectStandardError = true,
        RedirectStandardOutput = true
        };


        using(Process proc = Process.Start(startInfo))
        {
        proc.OutputDataReceived += ((sender, e) => MessageBox.Show("Data: " + e.Data ?? String.Empty));
        proc.ErrorDataReceived +=
        (sender, e) => MessageBox.Show(string.Format("Error: {0}", e.Data ?? string.Empty));
        proc.BeginErrorReadLine();
        proc.BeginOutputReadLine();

        proc.WaitForExit();
        }

        }

Wow. Nice piece of code isn't it? It will work for everything you have to execute. But if you execute XCOPY it won't work. We found out that it's missing something that should not be needed in our case but that cause XCOPY to just execute with no output and no results.

You want XCOPY to work? Just add this line before starting the process:

startInfo.RedirectStandardInput = true;

That's it! This error will only happen if you have "UseShellExecute" set to false.

Hope it help some clueless programmer that is wondering why the XCOPY won't execute.


Categories: c# | code snippet
Permalink | Comments (3) | Post RSSRSS comment feed

Implementing a Chain-of-responsibility or "Pipeline" in C#

Anti-Patterns are interesting in showing you what you are doing wrong. However, patterns are also interesting in showing you how to do it well.

This time, I want to show how to implement a simple Chain-of-responsibility pattern. Our example is going to be based on a simple e-Commerce data model.

The Domain Model

Product which will have some basic attributes like a price, a name and a collection of applied discounts.

Discount which is going to be an actual discount implementation. More class are going to be derived from this base class.

That is all we are going to need for this pattern. However, it would be smart to have a class that would assign discounts to product based on certain rules.

Let's start by writing our Product class and our Discount interface:

public class Product
        {
        private readonly List<IDiscount> _appliedDiscount = new List<IDiscount>();

        public string ProductName { get; private set; }
        public decimal OriginalPrice { get; private set; }

        public decimal DiscountedPrice
        {
        get
        {
        decimal discountedPrice = OriginalPrice;
        return discountedPrice;
        }

        }

        public Product(string productName, decimal productPrice)
        {
        ProductName = productName;
        OriginalPrice = productPrice;
        }

        public List<IDiscount> AppliedDiscount
        {
        get
        {
        return _appliedDiscount;
        }
        }
        }

        public interface IDiscount
        {
        decimal ApplyDiscount(decimal productPrice);
        }

Right now, the "DiscountedPrice" is simply returning our "OriginalPrice". Let's implement the proper discount commands:

public decimal DiscountedPrice
        {
        get
        {
        decimal discountedPrice = OriginalPrice;

        foreach (IDiscount discount in _appliedDiscount)
        discountedPrice = discount.ApplyDiscount(discountedPrice);

        return discountedPrice;
        }
        }

Now that we have an algorithm that will apply all discounts, let's create a few Discount class:

public class PercentageDiscount : IDiscount
        {
        public decimal PercentDiscount { get; set; }

        public PercentageDiscount(decimal percentDiscount)
        {
        PercentDiscount = percentDiscount;
        }

        public decimal ApplyDiscount(decimal productPrice)
        {
        return productPrice - (productPrice*PercentDiscount);
        }
        }

        public class FixPriceDiscount : IDiscount
        {
        public decimal PriceDiscount { get; set; }

        public FixPriceDiscount(decimal priceDiscount)
        {
        PriceDiscount = priceDiscount;
        }

        public decimal ApplyDiscount(decimal productPrice)
        {
        return productPrice - PriceDiscount;
        }
        }

So now we have a class that implement a percentage discount and another one that impose a fixed rate discount. Of course, our current implementation should NEVER be used in a real system as it is now. Validations must be done for a positive price and maybe some extra verification that we are not underselling the item.

Let's use this current implementation:

// Creating a product worth 50$
        Product currentProduct = new Product("Simple product", 50.0M);

        Console.WriteLine(string.Format("Original Price: {0}", currentProduct.OriginalPrice));

        // Give a 10% rebate on the product
        currentProduct.AppliedDiscount.Add(new PercentageDiscount(0.1M));
        Console.WriteLine(string.Format("Discounted Price: {0}", currentProduct.DiscountedPrice));

        //Give an extra 10$ off on the product
        currentProduct.AppliedDiscount.Add(new FixPriceDiscount(10.0M));
        Console.WriteLine(string.Format("Discounted Price: {0}", currentProduct.DiscountedPrice));

This will output in order 45.00$ and 35.00$.  It's important to be aware that the discount interfaces are not aware that they are being applied to a product. They could be reused in any other model that accepts an IDiscount.

Conclusion

By chaining Strategy Pattern (the discount algorithms), we can increase the amount of flexibility inside our model and increase the reuse of common algorithms. It would also be easy with a simple rule engine to apply discounts to product that match certain rules.

Other uses of a chain-of-responsibility could be when dealing with objects that could have multiple rules applied to them based on different conditions. The conditions would then be moved from the object itself to a "Command" and then reused exactly the same way we did here.


Categories: architecture | c# | pattern
Permalink | Comments (0) | Post RSSRSS comment feed

Part 3 - Advanced mocking functionalities of Moq

See also: Part 1 - Part 2

When you have some simple scenario like "when the method "GetTax" is called, return 5$" it's a simple scenario that a lot of mockers will see. However, there is some rarer scenario that people will wonder how to do it.

One of those scenario is with event handlers. The scenario would be like "if a Product is added to a ShoppingCart, a ProductAdded event should be fired".

Let's start with the basic class bellow which implement our scenario:

namespace MoqSamples
        {
        public interface IProduct
        {
        bool IsValid { get; }
        }

        public class ProductEventArgs : EventArgs
        {
        public ProductEventArgs(IProduct product)
        {
        Product = product;
        }

        public IProduct Product { get; private set; }
        }

        public class ShoppingCart
        {
        private readonly List<IProduct> Products = new List<IProduct>();
        public event EventHandler<ProductEventArgs> ProductAdded = delegate { };

        public void Add(IProduct product)
        {
        if (product.IsValid)
        {
        Products.Add(product);
        ProductAdded(this, new ProductEventArgs(product));
        }
        }
        }
        }

Event Handlers

What we want to test here, is every time we add a valid product an event ProductAdded should be fired.

I have played with Moq a bit trying to get it to work with ShoppingCart. As I tried to mock the event, I tried to create mocks and use the instructions on Moq site but wasn't able to make it happen. If I tried to mock the class itself it wouldn't allow me to do expectations even if I extracted an interface out of it. If I mock the interface, I lose the logic inside my class. I was thinking about creating a mocked event handlers and see if it ever get called but... you need a mock to create a mocked event handler. With this, we'll have to wait for Moq 3.0 (which is in beta at the moment of writing this article). Here is the test I came up with that didn't work :

[Test]
        public void Adding_A_Valid_Product_Fire_Event()
        {
        // Setup our product so that it always returns true on a IsValid verification
        Mock<IProduct> product = new Mock<IProduct>();
        product.Expect(currentProduct => currentProduct.IsValid).Returns(true);

        // setup an event argument for our event
        ProductEventArgs productEventArgs = new ProductEventArgs(product.Object);

        // setup a mocked shopping cart to create our mocked event handler and a true shopping cart to test
        Mock<ShoppingCart> mockedShoppingCart = new Mock<ShoppingCart>();

        //creating the event a mocked event
        MockedEvent<ProductEventArgs> mockedEvent = mockedShoppingCart.CreateEventHandler<ProductEventArgs>();
        mockedShoppingCart.Object.ProductAdded += mockedEvent;
        mockedShoppingCart.Expect(shopping => shopping.Add(product.Object)).Raises(mockedEvent, productEventArgs).Verifiable();

        //making the test
        IShoppingCart myShoppingCart = mockedShoppingCart.Object;
        myShoppingCart.Add(product.Object);

        mockedShoppingCart.Verify();
        }

And here is my simple fix to test this:

[Test]
        public void Adding_A_Valid_Product_Fire_Event()
        {
        // Setup our product so that it always returns true on a IsValid verification
        Mock<IProduct> product = new Mock<IProduct>();
        product.Expect(currentProduct => currentProduct.IsValid).Returns(true);

        // setup an event argument for our event
        ProductEventArgs productEventArgs = new ProductEventArgs(product.Object);

        // creating our objects and events
        ShoppingCart myShoppingCart = new ShoppingCart();
        bool isCalled = false;
        myShoppingCart.ProductAdded += (sender, e) => isCalled = true;

        // Testing the Add method if it fire the event
        myShoppingCart.Add(product.Object);

        // make sure the event was called
        Assert.AreEqual(isCalled, true);
        }

Way more small and more efficient with the mocking. Sometimes, it's better not to try to bend the framework and find the shortest solution that works.

Moq Factories

Moq have factories to help centralize the mocking configuration. The only two configuration available is CallBase and DefaultValue. Every mock created with the factories will allow you to reuse the configuration and reduce the amount of line for setting up the mock.

Here's a sample for the factory initialization:

[Test]
        public void Moq_Test_With_Factories()
        {
        // Initialize factories with default behaviours
        MockFactory mockFactory = new MockFactory(MockBehavior.Default);

        // Setup parameters for mocking
        mockFactory.CallBase = true;
        mockFactory.DefaultValue = DefaultValue.Mock;

        // create mocks with the factory
        Mock<IProduct> product = mockFactory.Create<IProduct>();
        }

This is of course really easy but... what about the parameters?

CallBase

CallBase is defined as "Invoke base class implementation if no expectation overrides the member. This is called "Partial Mock". It allows to mock certain part of a class without having to mock everything.

DefaultValue

There is 2 possible values here. One of them is "Empty" which return default value of the class. The one used in the example is "Mock" which allows "automocking". If a property is mockable, a mock is automatically returned.

Constructor

The constructor of the MockFactory needs a MockBehaviour parameter. 3 values are possible, Default, Loose and Strict.

Strict mock makes mocked object throw an exception for every call to a mocked object that doesn't have an expectation. Loose (which is also Default) will always return default values or empty arrays or null.

By using the factory properly, it's possible to set one style of mocking and reuse theses settings without having to rewrite 1 or 2 more lines per mock.


Categories: c# | mock | moq | unit test
Permalink | Comments (2) | Post RSSRSS comment feed