user3311522
user3311522

Reputation: 1658

Unit testing external service

I want to unit test a function that consumes an external dependency.

here is the method:

public string GetUrl(string records = "")
{
    if (records.IsNullOrEmpty())
    {
        records = Partner.Current["Records"];
    }

    return string.Format(
        "http://{0}/{1}?pid={2}",
        recordsdomain,
        HttpUtility.UrlEncode(FullName
            .Replace(' ', '_')
            .Replace("\\", string.Empty)
            .Replace("?", string.Empty)),
        Id);
}

this method is sitting inside a class which has a constructor as follows:

public Person(Person person)
{
      FullName = person.firstname + person.lastname
}

the problem is: Person does not have a public constructor, thats why it doesnt allow creating a mock for it.

Here is how person object is generated:

Person person = Service.GetPerson(Guid.Empty, "115763963", 1);

How to solve this?

UPDATE

The external service creates the person object and feeds the object off of its database. Also the object is declared on the external service so I cannot just create a new instance of it and feed the information into it.

Upvotes: 1

Views: 2283

Answers (2)

Alex
Alex

Reputation: 23300

If the external service functionality can be taken for granted, you could always fake it (bit of a burden but if you only need the data to test other code it might be viable).

Person person = Service.GetPerson(Guid.Empty, "115763963", 1);

would become

Person person = FakeService.GetPerson(Guid.Empty, "115763963", 1);

where you'd have something like

public static class FakeService
{
    public static Person GetPerson(Guid foo, string bar, int baz)
    {
        Person something = new Person{ /*Put nice data here*/ };
        return something;
    }
}

Maybe rough, but should get you going if you only need the service to provide you some data to work with, that is. If you also need to test the service itself, this approach would obviously be nonsensical.

UPDATE: Since Person's ctor is inaccessible, for this approach to work you're going to have to fake that too... One thing to immediately check is, if Person is a partial class you might be able to pull it off adding simply a new ctor to it (needs to be tried, been a while since i did something like this):

public partial class Person
{
    public Person(){}
}

I use this approach to expand auto-generated data context classes, it might work for you too.

On a less serious note, you could also ask for a public ctor overload to be added to that class!

Upvotes: 2

fan711
fan711

Reputation: 716

You need to use the mocking technique. You'd create a mock person object which return fixed values on firstname and lastname properties. You can then pass the mock person to the constructor.

Depending on which mock framework you choose the code would look different. Using Moq it would look something like:

var person = new Mock<Person>(); 
person.SetupGet(p => p.firstname).Returns("Joe");
person.SetupGet(p => p.firstname).Returns("Smith");
// your mock person does now return names for testing
// and you can pass it to the constructor

Upvotes: 1

Related Questions