การตั้งค่าขั้นต่ำสำหรับอินเทอร์เฟซพร้อมอาร์กิวเมนต์ของฟังก์ชัน

ฉันต้องการเขียน UnitTest ด้วย Moq 4.14.7 วิธีที่จะทดสอบมีดังนี้:

public IFoo Get(Guid id)
{
    Func<IFoo> getData = () => _repository.Get(id);
    if (_cache.TryGetAndSet(vaultId, getData, out var result))
    {
        return result;
    }
}

อธิบายสั้นๆ ครับ. ฉันมีคลาสแคชทั่วไป จะตรวจสอบในแคชหากมีเอนทิตีที่มี guid ที่ส่งผ่านอยู่ หากไม่เป็นเช่นนั้น จะมีการเรียกที่เก็บ

ตอนนี้ฉันมีการตั้งค่าแคชดังต่อไปนี้:

_cache.Setup
(
    x => x.TryGetAndSet
    (
        _vaultId,
        It.IsAny<Func<IFoo>>(),
        out foo
    )
)
.Returns(true);

จนถึงตอนนี้การทดสอบใช้งานได้ แต่ฉันยังไม่ครอบคลุม 100% เนื่องจากฟังก์ชั่นไม่ครอบคลุม

มีวิธีใดที่ดีกว่าการทำงานกับ It.IsAny และรับความคุ้มครอง 100% ที่นี่


person BenGeba    schedule 18.01.2021    source แหล่งที่มา
comment
การทดสอบนั้นครอบคลุมโค้ดที่คุณแสดง 100% อะไรเพราะ func ไม่ครอบคลุมหมายถึงอะไร ฉันเดาว่าคุณต้องการการทดสอบอื่นที่คืนค่าเป็นเท็จ?   -  person Liam    schedule 18.01.2021
comment
ไม่ ด้วยเครื่องมือ ReSharper UnitTestCoverage สามารถครอบคลุมได้เพียง 88% เท่านั้น และฟังก์ชันจะแสดงว่าไม่ครอบคลุม   -  person BenGeba    schedule 18.01.2021
comment
แต่ไม่ใช่สิ่งที่คุณต้องการทำใช่ไหม? เหตุใดจึงต้องครอบคลุมทั้งหมด?   -  person HimBromBeere    schedule 18.01.2021
comment
หากไม่มีสำเนาของเครื่องมือนี้ ฉันไม่รู้ว่ามันบ่นเรื่องอะไร หากคุณเพิ่มการทดสอบอื่นที่คืนค่าเป็นเท็จ มันจะหยุดบ่นหรือไม่ BTW การครอบคลุมโค้ด 100% เป็นเรื่องไร้สาระ   -  person Liam    schedule 18.01.2021
comment
GetData-func ดั้งเดิมของคุณไม่เคยถูกดำเนินการอย่างแน่นอน - และไม่ครอบคลุม - เนื่องจากคุณล้อเลียนฟังก์ชันการโทรเพียงฟังก์ชันเดียว - TryGetAndSet   -  person HimBromBeere    schedule 18.01.2021
comment
@HimBromBeere ถ้าฉันทำ _repo.Setup(x => x.Get(id)).Returns(It.IsAny<IFoo>); ก่อนหน้านี้ แต่ก็ยังไม่ถูกเรียกเพราะฉันมี It.IsAny<Func<IFoo>>() ในการจำลองแคช   -  person BenGeba    schedule 18.01.2021
comment
@Liam ไม่น่าเสียดายที่มันยังบ่นอยู่   -  person BenGeba    schedule 18.01.2021
comment
ผู้รับมอบสิทธิ์จะไม่ถูกดำเนินการ เนื่องจากฟังก์ชันเดียวที่เคยเรียกว่าถูกจำลองออกไป โดยพื้นฐานแล้วคุณพูดว่า: แทนที่ ทุก การโทรเป็น TryGetAndSet ด้วยสิ่งที่แตกต่างไปจากเดิมอย่างสิ้นเชิงซึ่งจะไม่มีวันแตะต้องผู้รับมอบสิทธิ์เลย   -  person HimBromBeere    schedule 18.01.2021
comment
ฉันได้ลองจำลองแคชแทน It.IsAny<> a () => _repository.Setup(m => m.Get(id)).Returns(foo) แล้ว แต่คาดว่า IFoo เป็นค่าส่งคืน แต่ได้รับ repo   -  person BenGeba    schedule 18.01.2021


คำตอบ (1)


บันทึกข้อโต้แย้งที่ส่งผ่านไปยังสมาชิกและเรียกใช้ฟังก์ชันตามต้องการ

//...

IFoo mockedFoo = Mock.Of<IFoo>();

IFoo foo = null;

_repo.Setup(_ => _.Get(It.IsAny<Guid>()).Returns(mockedFoo);

_cache
    .Setup(_ => _.TryGetAndSet(It.IsAny<Guid>(), It.IsAny<Func<IFoo>>(), out foo))
    .Returns((Guid vid, Func<IFoo> func, IFoo f) => {
        foo = func(); //<-- invoke the function and assign to out parameter.
        return true;
    });

//...

//Assertion can later verify that the repository.Get was invoked
//Assertion can later assert that foo equals mockedFoo

TryGetAndSet จะส่งกลับ true และอาร์กิวเมนต์ out จะส่งคืน mockedFoo ซึ่งเป็นการประเมินแบบขี้เกียจ

ข้อมูลอ้างอิง Moq Quickstart

person Nkosi    schedule 18.01.2021
comment
ขอบคุณที่ใช้งานได้ดี :) - person BenGeba; 18.01.2021