Как выполнить модульное тестирование защищенных свойств, которые должны быть установлены только NHibernate? - PullRequest
11 голосов
/ 24 сентября 2010

Я использую NHibernate для сохранения этой сущности:

public class Store
{
    public int Id { get; protected set; }
    public int Name { get; set; }
}

Обратите внимание, что свойство Id имеет защищенный установщик.Это сделано для того, чтобы пользователи не могли изменить Id, в то же время позволяя NHibernate назначать ему Id при сохранении его в базе данных.

В одном из моих модульных тестов я использую Moq сследующий код для макета моего репозитория:

var mock = new Mock<IRepository>();
mock.Setup(x => x.GetById<Store>(It.IsAny<int>()))
    .Returns(new Store { Value = "Walmart" }); // can't set the ID here

var store = Repository.GetById<Store>(5);
Assert.That(store.Id == 5);

Когда я говорю Moq вернуть новый экземпляр Store, я не могу присвоить идентификатор, и модульный тест не пройден.Как мне протестировать это свойство?Я не хочу изменять уровень доступа к свойству, потому что я не хочу, чтобы пользователи изменяли его вручную, и все же это именно то, что я должен сделать здесь, чтобы проверить его.

Ответы [ 4 ]

13 голосов
/ 24 сентября 2010

Просто, чтобы использовать это как еще один подход, вы могли бы сделать установщик protected internal:

public class Store
{
    public int Id { get; protected internal set; }
    public int Name { get; set; }
}

и используйте атрибут InternalsVisibleTo:

[assembly: InternalsVisibleTo("StoreUnitTests")]
11 голосов
/ 24 сентября 2010

Если вы на самом деле не тестируете класс Store, смоделируйте его и используйте метод SetupGet:

var mock = new Mock<IRepository>();
var mockStore = new Mock<Store>();
mock.Setup(x => x.GetById<Store>(It.IsAny<int>())).Returns(mockStore.Object);

mockStore.SetupGet(s => s.Id).Returns(5);
mockStore.SetupGet(s => s.Value).Returns("Walmart");

var store = Repository.GetById<Store>(5);
Assert.That(store.Id == 5);
4 голосов
/ 24 сентября 2010

В тестовом проекте создайте дочерний класс Store, который позволяет настраивать защищенные свойства.

class TestableStore : Store { 
  public int TestableId { 
    get { return Id; }
    set { Id = value; }
  }
}

Затем настройте свои модульные тесты на использование возврата этого экземпляра, когда вам нужно создать объект Store.

mock
  .Setup(x => x.GetById<Store>(It.IsAny<int>()))
  .Returns(new TestableStore { Value = "Walmart", TestableId=42 }); 
1 голос
/ 24 сентября 2010

Конечно, не лучший подход, но вы также можете использовать рефлексию для установки свойства, как это сделано в тестах Sharp Architecture.

...