Я видел много сообщений и вопросов о "Насмешке закрытого метода", но все еще не могу заставить ее работать и не нашел реальный ответ. Позволяет забывают запах кода, и Вы не должны делать этого и т.д....
Из того, что я понимаю, что сделал следующее:
1) Созданный библиотека классов "MyMoqSamples"
2) Добавленный касательно к Moq и NUnit
3) Отредактированный файл AssemblyInfo и добавил [блок: InternalsVisibleTo ("DynamicProxyGenAssembly2")] [блок: InternalsVisibleTo ("MyMoqSamples")]
4) Теперь должен протестировать закрытый метод. Так как это - закрытый метод, это не часть интерфейса.
5) добавленный следующий код
[TestFixture]
public class Can_test_my_private_method
{
[Test]
public void Should_be_able_to_test_my_private_method()
{
// TODO how do I test my DoSomthing method?
}
}
public class CustomerInfo
{
public string Name { get; set; }
public string Surname { get; set; }
}
public interface ICustomerService
{
List<CustomerInfo> GetCustomers();
}
public class CustomerService : ICustomerService
{
public List<CustomerInfo> GetCustomers()
{
return new List<CustomerInfo> { new CustomerInfo { Surname = "Bloggs", Name = "Jo" } };
}
protected virtual void DoSomething()
{
}
}
Вы могли предоставить мне пример о том, как Вы протестировали бы мой закрытый метод?Большое спасибо
Шаги, которые вы описываете, настраивают Moq для тестирования внутренних классов и членов, поэтому на самом деле они не имеют ничего общего с тестированием защищенного или частного метода
Тестирование частных методов - это немного запах , вам действительно стоит протестировать только общедоступный API. Если вы чувствуете, что метод действительно важен и его нужно тестировать изолированно, возможно, он заслуживает того, чтобы быть в своем собственном классе, где его затем можно протестировать самостоятельно?
Если ваше сердце настроено на тестирование защищенного метода, описанного выше, вы можете использовать свой собственный Mock в тестовой сборке:
public class CustomerServiceMock : CustomerService {
public void DoSomethingTester() {
// Set up state or whatever you need
DoSomething();
}
}
[TestMethod]
public void DoSomething_WhenCalled_DoesSomething() {
CustomerServiceMock serviceMock = new CustomerServiceMock(...);
serviceMock.DoSomethingTester();
}
Если бы он был частным, вы, вероятно, могли бы сделать что-нибудь хитрое с отражением, но этот путь - путь в ад .
Обновление
Хотя вы указали пример кода в своем вопросе, я действительно не понимаю, как вы хотите «протестировать» защищенный метод, поэтому я придумаю что-нибудь надуманное ...
Допустим ваша служба поддержки клиентов выглядит так: -
public CustomerService : ICustomerService {
private readonly ICustomerRepository _repository;
public CustomerService(ICustomerRepository repository) {
_repository = repository;
}
public void MakeCustomerPreferred(Customer preferred) {
MakePreferred(customer);
_repository.Save(customer);
}
protected virtual void MakePreferred(Customer customer) {
// Or more than likely some grungy logic
customer.IsPreferred = true;
}
}
Если вы хотите протестировать защищенный метод, вы можете просто сделать что-то вроде: -
[TestClass]
public class CustomerServiceTests {
CustomerServiceTester customerService;
Mock<ICustomerRepository> customerRepositoryMock;
[TestInitialize]
public void Setup() {
customerRepoMock = new Mock<ICustomerRepository>();
customerService = new CustomerServiceTester(customerRepoMock.Object);
}
public class CustomerServiceTester : CustomerService {
public void MakePreferredTest(Customer customer) {
MakePreferred(customer);
}
// You could also add in test specific instrumentation
// by overriding MakePreferred here like so...
protected override void MakePreferred(Customer customer) {
CustomerArgument = customer;
WasCalled = true;
base.MakePreferred(customer);
}
public Customer CustomerArgument { get; set; }
public bool WasCalled { get; set; }
}
[TestMethod]
public void MakePreferred_WithValidCustomer_MakesCustomerPreferred() {
Customer customer = new Customer();
customerService.MakePreferredTest(customer);
Assert.AreEqual(true, customer.IsPreferred);
}
// Rest of your tests
}
Имя этого «шаблона» - это подкласс Test (на основе терминологии тестовых шаблонов xUnit) для дополнительную информацию вы, возможно, захотите увидеть здесь: -
http://xunitpatterns.com/Test-Specific%20Subclass.html
На основании ваших комментариев и предыдущего вопроса кажется, что вам было поручено реализовать модульные тесты на каком-то устаревшем коде (или приняли решение самостоятельно). В этом случае библия всего унаследованного кода - это книга Майкла Фезерса. Он охватывает подобные методы, а также рефакторинг и методы, позволяющие разбить «непроверяемые» классы и методы на что-то более управляемое, и я настоятельно рекомендую это.
Похоже, что ваш вопрос состоит из двух частей.
Как мне высмеять защищенный метод:
http://blogs.clariusconsulting.net/kzu/mocking-protected-members-with-moq/
как мне вызвать вызов этого защищенного/частного поведения в моем тесте
Ответ здесь в том, что вы вызываете его через что-то публичное. Если вы хотите заставить это произойти напрямую (т.е. фактически вызвать что-то защищенное
напрямую без промежуточного помощника), вам придется использовать отражение. Это сделано специально - языки предоставляют механизмы защиты как способ обеспечения инкапсуляции.
Я советую вам подумать о том, что вы пытаетесь продемонстрировать/доказать в своем тесте. Если вы обнаружите, что пишете сложный тест, значит, вы делаете это неправильно. Возможно, то, что вы хотите сделать, можно разбить на независимые тесты? Возможно, вы пишете интеграционный, а не модульный тест? Но существует множество статей о плохих тестах, и все больше и больше будет становиться понятным для вас по мере того, как вы будете учиться писать хорошие тесты. Two of my favourites are http://www.codethinked.com/post/2009/06/30/What-is-Unit-Testing.aspx and http://www.codethinked.com/post/2009/11/05/Ite28099s-Okay-To-Write-Unit-Tests.aspx