简体   繁体   English

Spock 和 Groovy:变量赋值导致 null

[英]Spock and Groovy: variable assignment results in null

I have a problem with a test in Spock:我在 Spock 中的测试有问题:

@Subject
def mutation = new OrderedServicesMutation(long list of constructor elements here)

def "should order service and create address"() {
    given:
    def command = new OrderServiceCommand(1L, 2L, new Date(), "SomeAddress")
    def user = new User(id: command.userId)
    def address = new String()
    def service = new Service(id: command.serviceId)
    and:
    userRepository.findById(command.userId) >> Optional.of(user)
    serviceRepository.findById(command.serviceId) >> Optional.of(service)

    when:
    def result = mutation.orderService(command)

    then:
    with(result) {
        user == user
        address == address
        service == service
    }
}

OrderedServicesMutation.java: OrderedServicesMutation.java:

@Component
@AllArgsConstructor
public class OrderedServicesMutation implements GraphQLMutationResolver {

// imports removed for readibility

    @Transactional
@PreAuthorize("hasAnyAuthority('ACCOUNT_OWNER','USER')")
public OrderedService orderService(OrderServiceCommand command) {
    OrderedService orderedService = orderedServiceRepository.save(
            orderedServiceMapper.mapWithHistory(
                    userRepository.findById(command.getUserId()).orElseThrow(() -> new NotFoundException(User.class)),
                    command.getAddress(),
                    serviceRepository.findById(command.getServiceId()).orElseThrow(() -> new NotFoundException(Service.class)),
                    command.getDate()
            )
    );
    orderedServicePublisher.publish(orderedService);

    return orderedService;
}

The method should return an object of type OrderedService , and it normally is during runtime, but when I am running this test, I get:该方法应该返回一个 OrderedService 类型的OrderedService ,它通常是在运行时,但是当我运行这个测试时,我得到:

Target of 'with' block must not be null

Debugging the test shows me that the result variable is null...调试测试显示result变量是 null...

Why is Spock not assigning the result of mutation.orderService(command) to the result variable?为什么 Spock 没有将mutation.orderService(command)的结果分配给result变量?

You could mock the answer of Repository.save to have it return whatever it received during test execution:您可以模拟 Repository.save 的答案,让它返回在测试执行期间收到的任何内容:

and:
1 * orderedServiceRepository.save(_) >> { args -> args[0] }

Not that declaring receiving anything (_) would be a good practice in most cases.在大多数情况下,声明接收任何东西(_)并不是一个好习惯。 At least, you could specify the type of the argument like so: (_ as OrderedService) .至少,您可以像这样指定参数的类型: (_ as OrderedService)

Also using a closure would be Groovier:同样使用闭包的还有 Groovier:

result.with {
  assert it.user == user
  assert it.address == address
  assert it.service == service
}

I think you need the asserts inside the closure, not sure about when using it as a function like you did.我认为您需要闭包内的断言,不确定何时像您一样将其用作 function 。

It's also a good practice to add the cardinality so you know how many times a mock was called.添加基数也是一个很好的做法,这样您就知道调用了多少次模拟。

By the end, you could also make sure no more interactions were made to any of the declared mocks, which is great for making sure there aren't any unexpected interactions:最后,您还可以确保不再对任何已声明的模拟进行交互,这对于确保没有任何意外交互非常有用:

and: 'No more interactions'
0 * _

This is how I'd write this Specification:这就是我编写此规范的方式:

def "should order service and create address"() {
    given:
    def command = new OrderServiceCommand(1L, 2L, new Date(), "SomeAddress")
    def user = new User(id: command.userId)
    def address = new String()
    def service = new Service(id: command.serviceId)

    when:
    def result = mutation.orderService(command)

    then:
    1 * userRepository.findById(command.userId) >> Optional.of(user)

    and: 
    1 * serviceRepository.findById(command.serviceId) >> Optional.of(service)

    and:
    1 * orderedServiceRepository.save(_ as OrderedService) >> { args -> args[0] }

    and: 'Make sure Publisher receives correct OrderedService' // if you wish to do so
    1 * orderedServicePublisher.publish(_) >> { OrderedService arg ->
      assert arg.user == user
      assert arg.address == address
      assert arg.service == service
    }

    and: // don't really see why use with closure here
    result.user == user
    result.address == address
    result.service == service

    and: 'No more interactions'
    0 * _
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM