13

Currently in a part of my project a domain object like below exists:

public class Address
{
    public virtual string HouseName { get; set; }

    public virtual string HouseNumber { get; set; }

    public virtual string RoadName { get; set; }

    public virtual string Postcode { get; set; }

    public virtual string District { get; private set; }
}

The District property is a calculated column in the database. Due to the requirements of the data access provider (Entity Framework) a private set is required. This is fine in normal program flow as the District never needs to be set, due to it being updated when an Address record is saved/updated in the database

A method that I want to test looks like this:

public IEnumerable<House> GetHousesWithinSameDistrict (int addressId)
{
    var addressToMatch = _addressRepository
      .FirstOrDefault(address => address.Id == addressId)

    return _houseRepository
      .Where(house => house.Address.District == addressToMatch.District)
}

This is causing me problems when I try to set up the addressToMatch variable, as I am unable to set the District property and as such I cannot write a test to check correct matching addresses are returned.

How should I go about setting up an Address object for this test?

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
FLSH
  • 343
  • 1
  • 5
  • 15
  • Maybe, `protected internal` + `assembly:InternalsVisibleTo`? – Anton Gogolev Apr 29 '16 at 12:48
  • @DeblatonJean-Philippe Related, but certainly no duplicate IMHO. – Jeroen Apr 29 '16 at 12:53
  • @DeblatonJean-Philippe Not at all a duplicate of that. – FLSH Apr 29 '16 at 12:57
  • 1
    Making it `protected set` and creating a subclass with a setter method (as a private class of the testfixture) is a (not very pretty but pragmatic) workaround. – Jeroen Apr 29 '16 at 13:02
  • Sorry, I misunderstood this question. Thanks for pointing. – Deblaton Jean-Philippe Apr 29 '16 at 13:04
  • 1
    Without seeing your test it's hard to give advice, but you *could* use a Mock of the address you need to Match, and use SetupGet to return the value you want, You *could* set the value that you need to using reflection, or if you're using MS testing framework you could use PrivateObject to set the value. https://msdn.microsoft.com/en-us/library/ms244100.aspx – forsvarir Apr 29 '16 at 13:40

2 Answers2

20

This works out of the box if you're using Moq (which the question is tagged with, so I assume you are):

var mockAddress = new Mock<Address>();
mockAddress.SetupGet(p => p.District).Returns("Whatever you want to match");

So a more complete example is:

var mockAddress = new Mock<Address>();
mockAddress.SetupGet(p => p.Id).Returns(42);
mockAddress.SetupGet(p => p.District).Returns("What you want to match");

var mockAddressRepository = new Mock<IRepository<Address>>();
var addresses = new List<Address> { mockAddress.Object };
mockAddressRepository.Setup(p => p.GetEnumerator()).Returns(addresses.GetEnumerator());

var addressToMatch = mockAddressRepository.Object.FirstOrDefault(address => address.Id == 42);
Console.WriteLine(addressToMatch.District);

This outputs the expected value:

What you want to match
Patrick Quirk
  • 23,334
  • 2
  • 57
  • 88
  • 1
    This answer is all kinds of awesome. I was about to make my property internal and set InternalsVisibleTo. Or I was going to use PrivateObject. This answer is so easy and nice. Thank you. – Bob Horn Dec 23 '19 at 18:21
3

First, a wild guess: maybe a combination of declaring your District propery as protected internal plus adding an assembly:InternalsVisibleTo attribute to your "domain" assembly so that Distinct could be set from your tests.

class Address
{
    public virtual string District { get; protected internal set; }
}

Alternatively, you could add an internal constructor to your Address class, which would set the value of the District property. And again, annotate your "domain" assembly with assembly:InternalsVisibleTo.

Maarten
  • 22,527
  • 3
  • 47
  • 68
Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
  • Is there some alternative to using InternalsVisibleTo? It makes my code a little confusing and not clear (I am practicing ddd, so all of the properties' set in my classes are private), I would really appreciate if you could tell me some more elegant solution for this. Thanks – picaCHuXX Feb 01 '21 at 14:56