0

我见过开发人员使用 Spring 的 @Autowired 特性使 Spring 框架负责在测试类或夹具中实例化和注入 SUT(被测系统)或 CUT(被测类)。以下是显示在测试夹具中使用的 @Autowired 的片段:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.ExpectedException;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.test.context.ContextConfiguration;



interface BackingStore
{
    //Some methods
}


class Logger
{
    public Logger(BackingStore backingStore)
    {
        //Capture input parameter into member variables
    }

    public void Log(String message) 
    {
        //Some logic
    }
}

@ContextConfiguration(locations = { "classpath:someconfig.xml" })
public class LoggerTests extends AbstractTestNGSpringContextTests
{
    @Autowired
    private Logger _logger;

    @Test
    @ExpectedException(NullPointerException)
    public void Log_WhenPassedNull_ShouldThrowException()
    {
        _logger.Log(null);
    }
}

SUT 所需的所有依赖项(递归)都指定为 Spring 配置 XML 文件的一部分。我不喜欢这种方法。我喜欢所有的测试(单元或集成)都像故事一样阅读(我听到 Kent Beck 说同样的话 :))。我喜欢在测试用例本身中实例化 SUT/CUT,即使它很复杂。这给出了关于测试用例的清晰画面。

我对@Autowired 或用于在测试夹具中注入 SUT 的任何自动注入机制几乎没有顾虑:

  1. 它降低了测试代码的可读性。@Autowire 看起来像魔术。AAA 的排列(Arrange-Act-Assert)从测试代码移动到 XML 文件。

  2. 它降低了测试代码的可维护性。这是因为#2。

  3. 在异常情况下无法有效验证 SUT/CUT 抛出异常的构造函数。我对此不是 100% 确定的。我不知道 Spring 框架是否对此有答案。

  4. 对于单元测试或集成测试来说,这似乎有点矫枉过正。

我在这个问题上向专家索要 2 美分。

谢谢。

4

1 回答 1

1

It only reduces test code readability if you dont know where to look for the @Autowired objects. I would advise using SpringJunitTestRunner that defines the test application context at the top of the unit test class.

Using dependency injection in your test cases allows you to easily test with different objects.

E.g. If your code required a 3rd party service, you could use dependency injection (e.g. Autowiring a Spring bean) to inject a mocked service for your unit tests and the real service for the application.

So for this reason it definitley doesnt decrease the test code maintainability, as it is really encouraging loose coupling between the code youre testing and any external objects.

It may be overkill to inject all objects in such a way, but it is definitely not overkill for unit tests/integration tests in general.

于 2012-12-17T16:16:44.027 回答