San*_*osh 3 c# nunit unit-testing dependency-injection
我正在测试StoreManager类的功能,该类依赖于DataBaseConfiguration类.
public class StoreManager {
private DataBaseConfiguration dbConfig;
public void Store(string name) {
dbConfig.Store(name);
}
//other methods here
}
Run Code Online (Sandbox Code Playgroud)
StoreManager类存储到数据库,我可以测试此方法是否正常工作的唯一方法是从数据库进行查询.我有另一个班级在生产中这样做..
public class QueryManager {
private DataBaseConfiguration dbConfig;
public string Query(QueryExpression expr) {
//query logic
string name = "somename";
return name;
}}
Run Code Online (Sandbox Code Playgroud)
虽然我只关心测试我的StoreManager类,但它看起来像我需要使用QueryManager类来测试存储值.所以我有一个像这样的基本测试用例......
[TestFixture]
public class StoreManagerTest {
[TestFixtureSetup]
public void Setup() {
DatabaseConfiguration dbConfig = new DatabaseConfiguration(/*test database details*/);
StoreManager sm = new StoreManager(dbConfig);
QueryManager qm = new QueryManager(dbConfig);
}
[Test]
public void TestStore_ValidStore() {
sm.Store("testname");
string queryResult = qm.Query(new QueryExpression("query_expr"));
Assert.AreSame(queryResult, "testname");
}}
Run Code Online (Sandbox Code Playgroud)
如您所见,除了ClassUnderTest(即StoreManager)之外,QueryManager类还依赖于DatabaseConfig.
我在StoreManager类中没有很多逻辑,它只是委托DataBaseConfig类来存储(实际上存在更多涉及存储的类,而不是实际存储数据的DataBaseConfig ..但只是为了简单起见目的,让我们说..)
我想知道是否有更好的方法来处理这个测试而根本不涉及QueryManager?还有一种更好的方法将依赖于DataBaseConfiguration注入到StoreManager类中(考虑到DataBaseConfiguration类获取有关数据库的连接字符串等的详细信息,以便将数据存储到..并且我想传入一个测试数据库而不是那里的生产数据库连接字符串).
要在测试中获取依赖关系,最常见的方法是使用手写存根或模拟框架(即Moq或RhinoMocks).
此外,您必须允许StoreManager类的用户传入DataBaseConfiguration依赖项,否则您无法将其删除而无需更改代码.你现在正在做的构造函数注入是常见的做法和一种干净的方法(如果你有很多依赖项时使用IOC容器会变得更方便),也可以在这里看到.
如果我理解正确,你只想测试StoreManager实际存储你传递给它的值,你感兴趣的是它的行为StoreManager及其与它的依赖关系DataBaseConfiguration - 现在你通过查询数据存储本身来验证它.
鉴于让我们使用RhinoMocks进行一个简单的例子 - 我唯一改变的是将类中的Store方法定义DataBaseConfiguration为虚拟,以便RhinoMocks可以覆盖它.
//Arrange
string storeValue = "testname";
var dbConfigMock = MockRepository.GenerateMock<DataBaseConfiguration>();
dbConfigMock.Expect(x => x.Store(storeValue));
StoreManager sm = new StoreManager(dbConfigMock);
//Act
sm.Store(storeValue);
//Assert
dbConfigMock.AssertWasCalled(x => x.Store(storeValue));
Run Code Online (Sandbox Code Playgroud)
此测试验证Store方法被调用你的DataBaseConfiguration类W/O任何其他依赖-它测试的行为,你的StoreManager类.此测试不会触及数据库,也不会影响任何其他类.
编辑:
我不确定我是否理解在生产代码中使用模拟框架的问题 - 模拟框架仅用于您的测试项目,不参考它或生成代码本身需要任何代码更改.
使用手写存根,您可以"手动"执行相同的断言:定义一个测试存根,它存储多少次以及Store()调用的值(同样,这需要将Store方法声明为虚拟,以便可以覆盖它):
public class DataBaseConfigurationTest : DataBaseConfiguration
{
public int TimesCalled { get; set; }
public string LastNameStored { get; set; }
public DataBaseConfigurationTest()
{
TimesCalled = 0;
}
public override void Store(string name)
{
TimesCalled++;
LastNameStored = name;
}
}
Run Code Online (Sandbox Code Playgroud)
现在在测试中使用此测试存根而不是"真实" DataBaseConfiguration:
string storeValue = "testname";
DataBaseConfigurationTest dbConfigStub = new DataBaseConfigurationTest();
StoreManager sm = new StoreManager(dbConfigStub);
sm.Store(storeValue);
Assert.AreEqual(1, dbConfigStub.TimesCalled);
Assert.AreEqual(storeValue, dbConfigStub.LastNameStored);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
327 次 |
| 最近记录: |