Альтернативный способ сделать это должно создать обертку вокруг SmtpClient, который реализует тот же интерфейс. Затем введите и используйте обертку в своем классе. При выполнении поблочного тестирования можно затем заменить ложной оберткой, которая имеет ожидания вызовов метода и ответов.
РЕДАКТИРОВАНИЕ : обертка необходима (для RhinoMocks, по крайней мере), потому что SmtpClient не происходит из интерфейса и не имеет виртуальных методов. При использовании платформы насмешки, которая может дразнить класс без виртуальных методов непосредственно, можно пропустить обертку и ввести насмешку SmtpClient непосредственно.
public class SmtpClientWrapper
{
private SmtpClient Client { get; set; }
public SmtpClientWrapper( SmtpClient client )
{
this.Client = client;
}
public virtual void Send( MailMessage msg )
{
this.Client.Send( msg );
}
...
}
public class MyClass
{
private SmtpClientWrapper Client { get; set; }
public MyClass( SmtpClientWrapper client )
{
this.Client = client;
}
public void DoSomethingAndNotify()
{
...
this.Client.Send( msg );
}
}
Протестированный (с RhinoMocks) как:
public void DoSomethingAndNotifySendsAMessageTest()
{
SmtpClientWrapper client = MockRepository.GenerateMock<SmtpClientWrapper>();
client.Expect( c => c.Send( new MailMessage() ) ).IgnoreArguments();
MyClass klass = new MyClass( client );
klass.DoSomethingAndNotify();
client.VerifyAllExpectations();
}
Если у вас есть круговые зависимости между двумя объектами, это означает, что вам нужен третий объект, от которого будут зависеть два объекта, поэтому они не будут зависеть от друг с другом. Вот статья, которая является точным решением вашей проблемы:
http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/
DI предназначен не для разрешения циклических зависимостей, а для облегчения создания хорошо разделенных компонентов и, следовательно, более тестируемых.
Тот же ответ возвращается в следующих сообщениях (которые я добавлю для справок), которые создают третий класс, от которого оба зависят . Это означает: вы нарушаете принцип единой ответственности . Перемещая (извлекая) ответственность, от которой оба класса зависят, в отдельный класс, вы удалите циклическую зависимость.
К вашему сведению, шаблон единой ответственности в Википедии
Обсуждения StackOverflow другими:
Мой ответ на StackOverflow с примером выделения ответственности в отдельном классе.