关于单元测试中的依赖关系
我是单元测试的新手,但倾向于认为我相信编写精美的代码和正确设计的架构。
我的问题是。单元测试是否过于关注对象之间的依赖关系?当您的单元测试失败时,您会做什么,因为您的方法以前调用的依赖项不再被调用(设计决策),或者您的方法调用另一个方法或依赖项(再次是设计决策),您会重新设计您的测试吗?如果是这种情况,那么单元测试对于减少组件之间的耦合和提高组件之间的凝聚力几乎没有帮助。
也许我的观点太宽泛,但一般来说,人们如何在正确的单元测试中处理依赖关系。我想最好的方法是完全没有依赖关系,并且每个方法都依赖于为其提供的参数,但现实情况并非如此。此外,为每个可能的调用伪造每个依赖方法也有点主观并且浪费时间,因为在未来的某个时间点,被测试的类可能不再需要依赖关系。
I am new to unit testing, but tend to think that I believe in beautifully written code, and properly designed architectures.
My question is. Aren't unit tests focusing too much on dependencies between objects? What do you do when your unit test fails because a dependency your method used to call befor is no longer called (a design decision) or your method calls another method or a dependency (again a design decision) Do you redesign your tests? If that's the case, then unit testing helps very little to reduce couple and improve cohesion between components.
Maybe my opinion is too broad, but in general how do people treat dependencies in properly mannered unit tests. I guess that the best way would be to have no dependencies at all, and every method relied on the parameters that were given to it, but this is hardly the case in reality. In addition, faking every dependency method for every possible call is also a bit subjective and time wasting, because at a future point in time, the class under test may simply no longer need the dependency.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我建议您查看测试驱动开发(TDD),因为我相信这种技术将帮助您解决设计问题。通过在编写生产代码之前编写单元测试,您将需要考虑如何使生产代码可测试。这比先测试后的方法更好,在这种方法中,您首先编写生产代码,然后尝试围绕它们进行测试。
要处理依赖性,请考虑哪些依赖性给您带来了问题。
外部依赖项
如果您的测试使用外部资源(例如文件),那么您正在编写集成测试,而不是单元测试。我已经编写了许多使用外部文件的测试,并且我只是在测试项目中创建了该文件的副本。该文件副本将包含我的测试所需的虚拟数据。
如果您的测试需要数据库,那么您再次编写集成测试。我个人在我的 PC 上创建数据库的本地副本并对其运行测试。
对象依赖性
如果您担心代码依赖性(例如,如果私有方法的签名发生更改,您的测试将会失败),那么您正在错误的抽象级别上进行测试。我的意思是确保您的测试调用公共 API,而不是私有 API。为了巩固这一点,请为您的对象使用接口,以确保实现它的对象具有预期的契约。
我还建议您尝试使用模拟框架,例如 RhinoMocks、Moq 或 TypeMock
模拟框架将帮助您消除对例如可用于测试的数据库的依赖。我个人使用 TypeMock,它并不便宜,但它是迄今为止最强大的工具。
I would suggest that you look at Test Driven Development (TDD) as I believe this technique will help you with your design issues. By writing unit tests before writing the production code, you will need to think about how to make your production code testable. This is better then the test later approach, where you write the production code first and then try to shoe-horn tests around them.
To deal with dependencies, think about what dependencies are causing you problems.
External Dependencies
If your tests use an external resource, such as a file, then you are writing an integration test, not a unit test. I've written many tests that use an external file, and I simply created a copy of the file in my test project. This file copy will contain dummy data required for my tests.
If your test requires a database, then again your writing an integration test. Personally I create a local copy of the database on my PC and run my tests against it.
Object Dependencies
If you are worried about code dependencies (e.g. your test will fail if a private method's signature is changed) then you are testing at the wrong level of abstraction. By that I mean make sure that your tests are calling public API's and not private ones. To cement this point, use
interfaces
for your objects to ensure an expected contract for an object that implements it.I would also recommend that you try using a mocking framework such as RhinoMocks, Moq or TypeMock
A mocking framework will help you remove the dependency on, for example, having a database available for your tests. I personally use TypeMock, it's not cheap but it's by far the most powerful tool out there.
如果您正在谈论单元测试,那么您没有依赖项,因为单元测试仅测试单个类(Java、C++、Ruby、Python)。您所说的听起来更像是不同的集成测试。此外,如果你有太多的依赖,你的耦合就会很高,这不是很好,但当然并不总是可以避免的。
If you are talking about Unit testing you have no dependencies, cause a unit test tests only a single class (Java, C++, Ruby, Python). What you are talking about sounds more like integration testing which is different. Furthermore if you have to much dependencies your coupling is to high which is not very good, but of course not always avoidable.
单元测试应测试行为,而不是实现。这样,在更改实现或重构代码时就可以依赖单元测试。删除依赖项(例如通过内联类)不会破坏测试。
测试实现会导致脆弱的测试,这会妨碍重构。
Unit tests shall test the behavior, not the implementation. That way, one can rely on the unit tests when changing the implementation, or when refactoring the code. Removing a dependency (via inlining the class for instance), does not break the test.
Testing the implementation leads to brittle tests, that gets in the way when refactoring.