Ant P
Ant P

Reputation: 25221

Mocking concrete object properties with no setter

I'm testing a service that interfaces with a third-party system. The method exposed by the API returns objects that look something like this:

public class Thing
{
    public string Name { get {...} }
    public string Description { get {...} }

    public Thing(string someUri)
    {
        /* Do some secret internal stuff and
           populate all my properties. */
    }
}

I need to mock these properties in order to test that my service behaves correctly according to the objects returned.

The objects are instances of a concrete class that does not implement any interfaces that I can mock. The backing fields of these properties are set in the constructor of Thing, which takes a URI, goes off and fetches the object in some tightly-coupled third-party system and presumably sets the backing fields directly.

All of this means that I have no way to mock the properties - I can't set them directly, I can't mock an interface and I can't mock out the constructor dependencies and set the properties that way (which would diminish the usefulness of my tests anyway).

Is there any way around this?

Upvotes: 1

Views: 1379

Answers (3)

Joe Taylor
Joe Taylor

Reputation: 2175

You could just wrap the Thing -- this probably isn't the answer you're looking for because it will involve changes to the application code to support your unit testing, but it will result in a more loosely coupled code base and might make your life easier in the long run.

Create a ThingWrapper class that takes a Thing as a constructor argument and whose properties call the getters on the wrapped Thing instance. You can then

  • mark these properties as virtual and mock the wrapper directly (less code)
  • or have the wrapper implement an interface code against that interface (probably better).

Hope this helps, sorry if I'm just stating the obvious :/

Upvotes: 1

Sven Grosen
Sven Grosen

Reputation: 5636

Assuming you are using VS2012.2 or VS2013 in either Premium or Ultimate Edition, shims should get you what you need. They allow for "shimming" properties and constructors, ideally only for scenarios like the one you find yourself in (third-party library that doesn't use interfaces).

After adding a Fakes assembly for your library in your unit test project, you'd do something like this in your unit test:

using (ShimsContext.Create())
{
    ShimThing.ConstructorString = (@this, value) => {
        var shim = new ShimThing(@this) {
            NameGet = () => "Your Desired Name",
            DescriptionGet = () => "Your Desired Description"
        };
    };

    //do whatever you need to do that creates a Thing object
}

I wrote this example without actually trying it out, so the syntax of the ShimThing constructor might be slightly off.

Upvotes: 1

Jonas Jämtberg
Jonas Jämtberg

Reputation: 571

You can use Shims (build into visual studio) to fake a Thing

http://msdn.microsoft.com/en-us/library/hh549175.aspx

Upvotes: 1

Related Questions