【问题标题】:How to test a service or do it right mock? Java11, Spock Framework如何测试服务或正确模拟? Java11、Spock 框架
【发布时间】:2022-01-22 21:31:38
【问题描述】:

同学们,欢迎大家!告诉我如何决定,或如何行动。 (Java11, SpringBoot, testing - Spock Framework) 我需要写一个测试来测试一个类的方法,整个问题是被测类的方法通过继承调用另一个服务,在被测类中没有声明,但在它的抽象祖先中。如何测试这样的故事?如果这个服务是在被测类本身中声明的,那么一切都清楚了,我会在测试中创建一个模拟并将它传递给构造函数,但是如果这个服务位于祖先呢?我在下面附上一个示例代码。

// The class to be tested

@Service
public class ServiceForTest extends AbstractComponent{

    public String methodForTest (String s) {
        return someService.generateString(s);
    }

}

//An abstract class from which the tested one is inherited and which contains the service

public class AbstractComponent {

    @Autowired
    protected SomeService someService;

}

public interface SomeService {

    String generateString(String s);

}

@Service
public class SomeServiceImpl implements SomeService{

    @Override
    public String generateString(String s) {
        return s;
    }

}

下面是一个例子,如果服务在被测试的类中,我会做什么

//TestClass
@Service
public class ServiceForTest extends AbstractComponent{

    final SomeService someService;

    public ServiceForTest(SomeService someService) {
        this.someService = someService;
    }

    public String methodForTest (String s) {
        return someService.generateString(s);
    }

}

类测试 groovy,Spock 框架

class ServiceForTestTest extends Specification {

    ServiceForTest serviceForTest

    void setup(){
        SomeService someServiceMock = Mock(SomeService)
        someServiceMock.generateString("TEST") >> "TEST"
        serviceForTest = new ServiceForTest(someServiceMock)
    }

    def "Test for return current value"(){

        when:
        def methodForTest = serviceForTest.methodForTest("TEST")

        then:
        methodForTest == "TEST"

    }
}

【问题讨论】:

    标签: java unit-testing groovy mocking spock


    【解决方案1】:

    您使用@Autowired,即某种依赖注入框架,例如 Spring 或 Java EE CDI。这些框架具有测试支持。特别是对于 Spring 测试,Spock 有一个 Spring module 供您使用。我不是 Spring 用户,所以我不能告诉你具体怎么做,但是文档非常好。

    作为一般答案,即使没有任何框架支持,如果您按照约定将测试放入与被测类相同的包中,您也可以轻松测试它。因为您要注入模拟的字段是protected,这意味着对于 JVM,所有子类以及同一包中的其他类都可以访问它。即,您可以简单地设置值:

    serviceForTest = new ServiceForTest()
    serviceForTest.someService = someServiceMock
    

    或者,更优雅地使用隐式设置字段值的 Groovy 风格的构造函数:

    serviceForTest = new ServiceForTest(someService: someServiceMock)
    

    一般来说,我推荐构造函数或 setter 注入而不是依赖字段注入(尤其是当字段是私有的时),因为在可测试性方面,您对 DI 框架有严格的依赖,并且不能轻易编写单元测试。因此,如果您可以重构,我建议您这样做。您刚刚注意到,测试此类事情可能会让人头疼,除非您有出路,例如在受保护字段的这种特殊情况下。但这对重构并不是那么友好。

    【讨论】:

    • 非常感谢!)它成功了。我是来自俄罗斯的初学者 java 开发人员,我很高兴来自另一个国家的同事提供帮助)祝你一切顺利,身体健康
    • 我在 2009 年作为敏捷教练在俄罗斯与一群团队一起工作了几个月,帮助他们进行敏捷转型,有着非常美好的回忆。我也喜欢 Stack Overflow,因为我可以接触到来自世界各地的人。
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-09-05
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多