Вы правы относительно перемещения GetAgentFromDatabase () в отдельный класс. Вот как я переопределил AgentRepository :
public class AgentRepository {
private IAgentDataProvider m_provider;
public AgentRepository( IAgentDataProvider provider ) {
m_provider = provider;
}
public Agent GetAgent( int agentId ) {
Agent agent = null;
using( IDataReader agentDataReader = m_provider.GetAgent( agentId ) ) {
if( agentDataReader.Read() ) {
agent = new Agent();
// set agent properties later
}
}
return agent;
}
}
где я определил интерфейс IAgentDataProvider следующим образом:
public interface IAgentDataProvider {
IDataReader GetAgent( int agentId );
}
Итак, AgentRepository - это тестируемый класс. Мы будем издеваться IAgentDataProvider и вставлять зависимость. (Я сделал это с Moq , но вы можете легко переделать его с помощью другой изолированной структуры).
[TestFixture]
public class AgentRepositoryTest {
private AgentRepository m_repo;
private Mock<IAgentDataProvider> m_mockProvider;
[SetUp]
public void CaseSetup() {
m_mockProvider = new Mock<IAgentDataProvider>();
m_repo = new AgentRepository( m_mockProvider.Object );
}
[TearDown]
public void CaseTeardown() {
m_mockProvider.Verify();
}
[Test]
public void AgentFactory_OnEmptyDataReader_ShouldReturnNull() {
m_mockProvider
.Setup( p => p.GetAgent( It.IsAny<int>() ) )
.Returns<int>( id => GetEmptyAgentDataReader() );
Agent agent = m_repo.GetAgent( 1 );
Assert.IsNull( agent );
}
[Test]
public void AgentFactory_OnNonemptyDataReader_ShouldReturnAgent_WithFieldsPopulated() {
m_mockProvider
.Setup( p => p.GetAgent( It.IsAny<int>() ) )
.Returns<int>( id => GetSampleNonEmptyAgentDataReader() );
Agent agent = m_repo.GetAgent( 1 );
Assert.IsNotNull( agent );
// verify more agent properties later
}
private IDataReader GetEmptyAgentDataReader() {
return new FakeAgentDataReader() { ... };
}
private IDataReader GetSampleNonEmptyAgentDataReader() {
return new FakeAgentDataReader() { ... };
}
}
(я исключил реализацию класса FakeAgentDataReader , который реализует IDataReader и тривиален - вам нужно только реализовать Read () и Dispose () , чтобы тесты работали.)
Цель AgentRepository здесь состоит в том, чтобы взять IDataReader объекты и превратить их в правильно сформированные Agent объекты. Вы можете расширить вышеуказанное тестовое устройство, чтобы проверить более интересные случаи.
После модульного тестирования AgentRepository в отрыве от реальной базы данных вам потребуются модульные тесты для конкретной реализации IAgentDataProvider , но это тема отдельного вопроса. НТН