gpt4 book ai didi

kotlin - 用 Mockito 在 Kotlin 中模拟队列似乎不起作用

转载 作者:行者123 更新时间:2023-12-02 13:34:49 24 4
gpt4 key购买 nike

我有一个使用队列的简单命名服务:

@Named
class OrderFormService @Inject constructor(
private val repository: OrderFormRepository
) {
private val queue: Queue<OrderForm> = LinkedList()

private val logger: Logger = LoggerFactory.getLogger("service")

fun getNextOrderForm(input: GetNextOrderFormInput): GetNextOrderFormPayload? {
if (queue.isEmpty()) {
logger.info("queue is empty")

val forms: List<OrderForm> = repository.findTop1000ByImageTypeAndImageState(input.type, input.state)

forms.forEach {
queue.offer(it)
}
}

if (!queue.isEmpty()) {
return GetNextOrderFormPayload(queue.poll())
}

return null
}
}

在尝试对此进行单元测试时,我想模拟队列:
@ExtendWith(MockitoExtension::class)
internal class OrderFormServiceTest {

@Mock
private val queue: Queue<OrderForm> = LinkedList()

@Mock
lateinit var repository: OrderFormRepository

@InjectMocks
lateinit var service: OrderFormService


@Test
fun givenValidInputAndFilledQueueWhenGetNextOrderFormThenReturnPayload() {
// given
val expected = createOrderForm()
val expectedPayload = GetNextOrderFormPayload(expected)

given(queue.isEmpty()).willReturn(false)
given(queue.poll()).willReturn(expected)

// when
val input = GetNextOrderFormInput(ImageType.NUMBER, ImageState.UNCLASSIFIED)
val result = service.getNextOrderForm(input)

// then
assertThat(result).isEqualTo(expectedPayload)
}
}

但是队列总是空的。所以我猜队列没有被正确地 mock 。我究竟做错了什么?

编辑

我尝试过的事情:
  • 使队列不是最终的:
  • ...
    var queue: Queue<OrderForm> = LinkedList()
    ...
  • 使用 Mockito.mock :
  • ...
    var queue = Mockito.mock(Queue::class.java)

    `when`(queue.isEmpty()).thenReturn(false)
    `when`(queue.poll()).thenReturn(expected)
    ...

    最佳答案

    您的队列未标记为 @Autowired或构造函数的一部分,因此 Mockito 无法模拟它。

    为了使这项工作(尽管尚未验证),请像这样定义您的构造函数:

    @Named
    class OrderFormService @Inject constructor(
    private val repository: OrderFormRepository,
    private val queue: Queue<OrderForm>
    ) { }

    现在,为了在常规程序中初始化队列,您必须为它定义一个 bean,例如:
    @Configuration
    class QueueConfiguration {
    @Bean
    fun queue() : Queue<OrderForm> = LinkedList()
    }

    此外,您应该注意 @InjectMocks只会使用一种注入(inject)方法。因此,您不能将构造函数初始化与属性 setter 或字段注入(inject)混合在一起。

    也看看 @MockBean .这会全局替换bean,使用起来会更方便。它的缺点是它弄脏了上下文,如果没有正确切分,会导致上下文重新初始化和可能更慢的测试。

    编辑:

    另一种选择是手动设置模拟(样本未验证,希望它们对您有用)。我建议使用 https://github.com/nhaarman/mockito-kotlin使 Mockito 语法更加 kotlinish。

    手动设置模拟需要使队列成为可公开设置的属性:
    @Named
    class OrderFormService @Inject constructor(
    private val repository: OrderFormRepository
    ) {
    var queue: Queue<OrderForm> = LinkedList()
    }

    然后,您在测试中分配模拟:
    internal class OrderFormServiceTest {

    private val queue: Queue<OrderForm> = mock {}

    @Mock
    lateinit var repository: OrderFormRepository

    @InjectMocks
    lateinit var service: OrderFormService

    @BeforeEach
    fun setup() {
    service.queue = queue
    }
    }


    但是有一个问题:根据您使用的框架,您的 OrderFormService可能只初始化一次。设置队列时,您更改了可能影响其他测试的全局对象。为了缓解这种情况, @DirtiesContext在您的测试中将确保重建整个上下文(这会影响测试性能)。这或多或少与 @MockBean 相同。会为你做(具有相同的性能影响)。不过,您也可以自己清洁物体。

    关于kotlin - 用 Mockito 在 Kotlin 中模拟队列似乎不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58991373/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com